Skip to content

fix(frontend): resolve set-state-in-effect in SettingsPage (#1063)#1074

Merged
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-settings-page
May 1, 2026
Merged

fix(frontend): resolve set-state-in-effect in SettingsPage (#1063)#1074
ericsocrat merged 1 commit intomainfrom
chore/react-compiler-settings-page

Conversation

@ericsocrat
Copy link
Copy Markdown
Owner

Phase 2 of #1063 - sixth PR, seventh violation of 19. Resolves src/app/app/settings/page.tsx:57.

Change

Replaces a useEffect that synced country/language state from a useQuery prefs result with the React 19 'adjust state during render' pattern (https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes).

A prevPrefs state variable tracks the last seen query result; when the prefs reference changes, the new values are written before render completes.

Behaviour is unchanged - the form still populates after the query resolves and after refetches.

Verification

  • eslint src/app/app/settings/page.tsx - clean
  • vitest run src/app/app/settings/page.test.tsx - 14/14 pass
  • tsc --noEmit - clean

Progress

Replaces useEffect that synced country/language state from useQuery prefs result with the React 19 'adjust state during render' pattern (https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes). A prevPrefs state tracks the last seen query result; when prefs identity changes, the new values are written before render completes. Behaviour is unchanged - the form still populates after the query resolves and after refetches.
Copilot AI review requested due to automatic review settings May 1, 2026 11:07
@ericsocrat ericsocrat enabled auto-merge (squash) May 1, 2026 11:07
@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 11:09am

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

  • settings

📥 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

This PR removes a useEffect-based state sync in the Settings/Profile page to resolve the React Compiler set-state-in-effect warning by switching to the “adjust state during render when upstream data changes” pattern.

Changes:

  • Replaced the useEffect([prefs]) that populated country/language from React Query prefs with a render-time guarded sync using prevPrefs.
  • Added inline documentation referencing the React “you might not need an effect” guidance.

Comment on lines +57 to 63
const [prevPrefs, setPrevPrefs] = useState(prefs);
if (prefs !== prevPrefs) {
setPrevPrefs(prefs);
if (prefs) {
setCountry(prefs.country ?? "");
setLanguage((prefs.preferred_language ?? "en") as SupportedLanguage);
}
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.

prevPrefs is initialized with prefs, so if React Query returns cached preferences on the first render (likely since RouteGuard already caches queryKeys.preferences), the if (prefs !== prevPrefs) branch will never run and country/language will stay at their default values. This is a behavioral regression vs the previous effect, which populated state even when prefs was available immediately. Consider initializing country/language from prefs via lazy useState initializers, or initialize prevPrefs to a sentinel (e.g., undefined) so the first non-undefined prefs triggers the sync.

Copilot uses AI. Check for mistakes.
@ericsocrat ericsocrat merged commit b229a4d into main May 1, 2026
21 of 22 checks passed
@ericsocrat ericsocrat deleted the chore/react-compiler-settings-page branch May 1, 2026 11:12
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