Skip to content

fix(frontend): resolve set-state-in-effect in MoreDrawer (#1063)#1072

Merged
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-more-drawer
May 1, 2026
Merged

fix(frontend): resolve set-state-in-effect in MoreDrawer (#1063)#1072
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-more-drawer

Conversation

@ericsocrat
Copy link
Copy Markdown
Owner

Phase 2 of #1063 — fourth of 19 react-hooks/set-state-in-effect violations.

Change

Splits the open-tracking effect in MoreDrawer into two parts:

  1. Resetting animating to false on close is moved out of the effect into the canonical adjust-state-during-render pattern, gated by a prevOpen state.
  2. Enabling the animation on open stays in an effect, but the setAnimating(true) call is inside requestAnimationFrame, so it's asynchronous and does not violate the rule. Added a cancelAnimationFrame cleanup for safety.

Behaviour is unchanged: the drawer still gets a one-frame delay before the open class is applied (so CSS transitions run from the closed state), and closes immediately reset the animation flag.

Verification

  • eslint src/components/layout/MoreDrawer.tsx — clean
  • vitest run src/components/layout/MoreDrawer.test.tsx — 17/17 pass
  • tsc --noEmit — clean

Progress

Splits the open-tracking effect: resetting animating to false on close is now done during render via the adjusting-state-during-render pattern, while enabling animation on open stays in an effect (the setAnimating(true) call lives inside requestAnimationFrame, so it is asynchronous and does not trip the rule).
Copilot AI review requested due to automatic review settings May 1, 2026 10:45
@ericsocrat ericsocrat enabled auto-merge (squash) May 1, 2026 10:45
@vercel
Copy link
Copy Markdown

vercel Bot commented May 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tryvit Ready Ready Preview, Comment May 1, 2026 10:47am

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 1, 2026

📸 PR Screenshots

Captured 2 screenshots (1 mobile, 1 desktop) for 1 changed page(s):

  • dashboard

📥 Download screenshots from workflow artifacts.

Captured by PR Screenshots workflow • 2026-05-01

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 1, 2026

Bundle Size Report

Metric Value
Main baseline 0 KB
This PR 0 KB
Delta +0 KB (+0%)
JS chunks 0
Hard limit 4000 KB

✅ Bundle size is within acceptable limits.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates MoreDrawer to eliminate a react-hooks/set-state-in-effect lint violation while preserving the drawer’s animation timing (one-frame delay on open, immediate reset on close).

Changes:

  • Moves the “reset animating on close” logic into a render-phase “adjust state during render” pattern gated by prevOpen.
  • Keeps “enable animation on open” in an effect, but defers setAnimating(true) via requestAnimationFrame and adds cancelAnimationFrame cleanup.

Comment on lines +99 to 114
// Reset animation immediately when the drawer closes — done during render
// (https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes)
// rather than in an effect to satisfy react-hooks/set-state-in-effect.
if (open !== prevOpen) {
setPrevOpen(open);
if (!open) setAnimating(false);
}

// Defer enabling the animation class to the next frame so CSS transitions
// run from the closed state. setState inside requestAnimationFrame is
// asynchronous, so it does not violate set-state-in-effect.
useEffect(() => {
if (open) {
requestAnimationFrame(() => setAnimating(true));
} else {
setAnimating(false);
}
if (!open) return;
const id = requestAnimationFrame(() => setAnimating(true));
return () => cancelAnimationFrame(id);
}, [open]);
Copy link

Copilot AI May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new open/close animation sequencing logic (render-phase reset via prevOpen and deferred setAnimating(true) via requestAnimationFrame) isn’t covered by tests. Consider adding a regression test that toggles open (using rerender) and asserts the drawer/backdrop classes start in the non-animating state and only flip after the rAF callback runs (and that a close transition resets the animation state before the next open).

Copilot uses AI. Check for mistakes.
@ericsocrat ericsocrat merged commit ef6a194 into main May 1, 2026
22 checks passed
@ericsocrat ericsocrat deleted the chore/react-compiler-more-drawer branch May 1, 2026 10:50
ericsocrat added a commit that referenced this pull request May 1, 2026
…) (#1077)

Phase 2 of #1063 -- resolves 2 of 19 violations (running total: 12/19 across 9 PRs).

Two react-hooks/set-state-in-effect warnings in SearchAutocomplete.tsx resolved by adjusting state during render:

1. Refresh recent-searches list on dropdown open: replaced the show-dep useEffect with a prevShow render-phase tracker. Added a lazy initial-state initializer so the list is hydrated on mount when show is already true (preserves existing test contract).

2. Reset activeIndex when suggestions/query change: replaced the multi-dep useEffect with a composite resetKey + prevResetKey render-phase tracker.

Pattern: https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes

Behaviour unchanged. 32/32 vitest pass, eslint and tsc clean.

Cross-references: #1067, #1069, #1070, #1071, #1072, #1073, #1074, #1075, #1076.

Co-authored-by: ericsocrat <ericsocrat@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants