PR #151 opened: fix: resolve react-hooks/no-set-state-in-effect violations
Summary
eslint-plugin-react-hooks 7.1 (incoming via the next minor-and-patch bundle #148) enables no-set-state-in-effect, which catches 6 real violations across 4 components. This PR fixes them all on main so:
- the bundle update (#148) can merge cleanly
- the eslint 9 → 10 major (#112) unblocks once it rebases
All four fixes follow React 19 patterns — no rule suppressions, no behavioural changes.
Per-file changes
ui/money-input.tsx — split into typedValue (focus-local state) and a derived displayValue computed from the value prop during render. Removes the effect that synced displayValue from props.
ui/file-upload.tsx — split prop-driven preview from upload-driven local state. Uses the React 19 "previous prop in state" pattern (if (prevCurrentUrl !== currentUrl) { setPrev...; reset locals; }) to handle parent prop changes without an effect. Preserves the existing override-on-prop-change semantics.
ui/address-autocomplete.tsx — derive hasSelectedPlace from value during render (eliminates one effect). Seed initial isLoaded and loadError via useState initializers (handles the "already-loaded" and "missing API key" cases without a synchronous setState in the load effect). Remaining setState calls in the load effect happen inside setInterval / script lifecycle callbacks, which the rule allows.
notification-bell.tsx — rewrite fetchNotifications as a .then/.catch/.finally promise chain so all setState calls happen inside promise callbacks (allowed by the rule) instead of in effect bodies.
Verification
-
npm run lint— clean -
npm run types— clean (the pre-existing TS5101 about deprecatedbaseUrlin tsconfig is untouched, separate concern) -
npm run build— clean - Manually loaded the homepage + register pages via Playwright; no console errors from the refactored components
Test plan
- Verify MoneyInput in pricing flow: focus, type, blur, refocus → typed value formatted correctly
- Verify FileUpload in profile flow: upload → preview shown; remove → cleared; parent change of currentUrl → preview updates to new URL
- Verify AddressAutocomplete in onboarding: search, select place, clear → input reappears
- Verify NotificationBell: bell shows correct unread count; dropdown re-fetches on open