Skip to content

fix(frontend): resolve set-state-in-effect in RouteAnnouncer (#1063 Phase 2)#1069

Merged
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-route-announcer
May 1, 2026
Merged

fix(frontend): resolve set-state-in-effect in RouteAnnouncer (#1063 Phase 2)#1069
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-route-announcer

Conversation

@ericsocrat
Copy link
Copy Markdown
Owner

Summary

Resolves 1 of 19 react-hooks/set-state-in-effect violations from #1063 Phase 2.

Replaces useEffect + useRef with React's canonical adjusting-state-during-render pattern, which the React Compiler accepts.

Why this is safe

  • Behaviour preserved: initial render produces no announcement (lastPathname initialised to current pathname, if-block skipped), pathname change triggers announcement.
  • Tests unchanged: all 11 existing tests in RouteAnnouncer.test.tsx pass — they assert behaviour (aria attributes, announcement text per route), not implementation.
  • Single-file scope: no API or component contract changes.

Phase 2 progress

File Status
RouteAnnouncer.tsx ✅ this PR
13 other files (18 violations) ⏸ deferred — each needs per-component review

Verification

  • npx eslint src/components/common/RouteAnnouncer.tsx — clean
  • npx vitest run src/components/common/RouteAnnouncer.test.tsx — 11/11 pass
  • npx tsc --noEmit — 0 errors

Closes part of #1063.

…hase 2)

Replace useEffect+useRef pattern with React's canonical 'adjusting state
during render' pattern (https://react.dev/learn/you-might-not-need-an-effect).

When pathname changes, setState is called during render, which React handles
specially by scheduling an immediate re-render without committing the
discarded one. Compatible with React Compiler — eliminates the
react-hooks/set-state-in-effect violation.

Initial render produces no announcement because lastPathname is initialised
to the current pathname (if-block skipped). All 11 existing tests pass
unchanged — they assert behavior, not implementation.

Phase 2 progress: 1/19 violations resolved, 18 remaining across 13 files.
Copilot AI review requested due to automatic review settings May 1, 2026 09:49
@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 9:50am

@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):

  • common-dashboard

📥 Download screenshots from workflow artifacts.

Captured by PR Screenshots workflow • 2026-05-01

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 RouteAnnouncer to eliminate a react-compiler/set-state-in-effect warning by switching from useEffect + useRef to React’s render-phase “adjust state during render” pattern while preserving the existing screen-reader announcement behavior.

Changes:

  • Removes useEffect/useRef-based first-render gating.
  • Introduces lastPathname state initialized from usePathname() and updates announcement during render when the pathname changes.

@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.

@ericsocrat ericsocrat merged commit 738bae7 into main May 1, 2026
22 checks passed
@ericsocrat ericsocrat deleted the chore/react-compiler-route-announcer branch May 1, 2026 09:53
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>
ericsocrat added a commit that referenced this pull request May 1, 2026
…#1078)

Resolves 3 react-hooks/set-state-in-effect violations in src/app/app/search/page.tsx (Phase 2 of #1063):

- Mount-load effect: replaced with lazy useState initializers for recentSearches, showAvoided, viewMode (helpers already SSR-safe via globalThis.localStorage guards)

- debouncedQuery sync effect: replaced with Pattern A render-phase tracker (composite submitKey of debouncedQuery + filters)

- page reset effect: replaced with Pattern A render-phase tracker (composite pageResetKey of submittedQuery + filters)

Validated: 54/54 vitest pass, eslint clean, tsc clean. Phase 2 cumulative: 15/19 (final non-deferred multi-violation file).

Cross-refs: #1067 (Phase 1), #1069-#1077 (Phase 2 micro-PRs).

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