Score: 83/100 · 1 error · 43 warnings
Copy as prompt
Fix the following React Review diagnostics in my codebase.
## Errors (1)
1. [error] effect-needs-cleanup — apps/terminal/src/components/terminal.tsx:221
useEffect subscribes via `addEventListener(...)` but never returns a cleanup - leaks the registration on every re-run and on unmount. Return a cleanup function that calls the matching remove/unsubscribe call
## Warnings (43)
2. [warning] unused-type-export — apps/terminal/src/lib/errors.ts:52
The exported symbol "WebErrorCode" is not referenced by reachable modules.
3. [warning] unused-type-export — apps/terminal/src/lib/errors.ts:53
The exported symbol "WebErrorKind" is not referenced by reachable modules.
4. [warning] unused-type-export — apps/terminal/src/lib/local-fonts-types.ts:1
The exported symbol "LocalFontData" is not referenced by reachable modules.
5. [warning] unused-export — apps/terminal/src/lib/schemas.ts:2
The exported symbol "clientToServerMessageSchema" is not referenced by reachable modules.
6. [warning] unused-export — apps/terminal/src/lib/terminal-fonts.ts:18
The exported symbol "buildLocalTerminalFont" is not referenced by reachable modules.
7. [warning] unused-type-export — apps/terminal/src/lib/terminal-themes.ts:3
The exported symbol "TerminalTheme" is not referenced by reachable modules.
8. [warning] unused-type-export — apps/terminal/src/utils/restore-terminal-scroll-anchor.ts:6
The exported symbol "TerminalScrollAnchorRestorer" is not referenced by reachable modules.
9. [warning] unused-file — apps/terminal/tests/setup.ts:0
This source file is not reachable from any package, framework, test, or support entrypoint.
10. [warning] unlisted-dependency — apps/terminal/package.json:0
"@types/vite/client" is referenced by tsconfig.json but not listed in the workspace package.json.
11. [warning] unlisted-dependency — apps/terminal/package.json:0
"vp" is used by package.json scripts but not listed in the workspace package.json.
12. [warning] unused-dependency — apps/terminal/package.json:0
"@xterm/addon-web-fonts" is listed in dependencies but not used.
13. [warning] unused-dev-dependency — apps/terminal/package.json:0
"jsdom" is listed in devDependencies but not used.
14. [warning] type-only-dependency — apps/terminal/src/lib/terminal-session-info.ts:1
"zod" is only used in type positions.
15. [warning] runtime-dev-dependency — apps/terminal/src/main.tsx:2
"react-grab" is imported by runtime code but listed in devDependencies.
16. [warning] runtime-dev-dependency — apps/terminal/vite.config.ts:2
"@tailwindcss/vite" is imported by runtime code but listed in devDependencies.
17. [warning] runtime-dev-dependency — apps/terminal/vite.config.ts:3
"@vitejs/plugin-react" is imported by runtime code but listed in devDependencies.
18. [warning] runtime-dev-dependency — apps/terminal/vite.config.ts:4
"vite" is imported by runtime code but listed in devDependencies.
19. [warning] barrel-hotspot — apps/terminal/src/lib/constants.ts:0
This module exports 61 symbols and is imported by 43 modules.
20. [warning] barrel-hotspot — apps/terminal/src/lib/terminal-fonts.ts:0
This module exports 6 symbols and is imported by 6 modules.
21. [warning] barrel-hotspot — apps/terminal/src/utils/favicon-state-store.ts:0
This module exports 7 symbols and is imported by 4 modules.
22. [warning] rerender-memo-before-early-return — apps/terminal/src/components/ui/field.tsx:173
useMemo returning JSX runs before an early return - extract the JSX into a memoized child component so the parent bails out before the subtree renders
23. [warning] rerender-memo — apps/terminal/src/components/ui/field.tsx:173
useMemo returns JSX - extract the expensive subtree into a memoized child component so parent early returns and prop equality can skip the work
24. [warning] no-array-index-as-key — apps/terminal/src/components/ui/field.tsx:190
Array index "index" used as key - causes bugs when list is reordered or filtered
25. [warning] click-events-have-key-events — apps/terminal/src/components/ui/input-group.tsx:48
Enforce a clickable non-interactive element has at least one keyboard event listener.
26. [warning] label-has-associated-control — apps/terminal/src/components/ui/label.tsx:9
A form label must be associated with a control.
27. [warning] js-tosorted-immutable — apps/terminal/src/utils/query-local-fonts.ts:22
[...array].sort() - use array.toSorted() for immutable sorting (ES2023)
28. [warning] no-autofocus — apps/terminal/src/components/local-font-picker.tsx:72
The `autoFocus` attribute is found here, which can cause usability issues for sighted and non-sighted users.
29. [warning] no-autofocus — apps/terminal/src/components/local-font-picker.tsx:212
The `autoFocus` attribute is found here, which can cause usability issues for sighted and non-sighted users.
30. [warning] effect-no-adjust-state-on-prop-change — apps/terminal/src/components/local-font-picker.tsx:111
state adjusted from a prop-change effect - derive during render or reset state directly while rendering instead of synchronizing after paint
31. [warning] effect-no-adjust-state-on-prop-change — apps/terminal/src/components/local-font-picker.tsx:113
state adjusted from a prop-change effect - derive during render or reset state directly while rendering instead of synchronizing after paint
32. [warning] async-defer-await — apps/terminal/src/components/local-font-picker.tsx:119
await blocks the function before an early-return that doesn't use the awaited value - move the await after the synchronous guard so the skip path stays fast
33. [warning] js-tosorted-immutable — apps/terminal/tests/lib/terminal-scrollback.test.ts:11
[...array].sort() - use array.toSorted() for immutable sorting (ES2023)
34. [warning] exhaustive-deps — apps/terminal/src/components/terminal.tsx:441
React Hook useEffect has a missing dependency: 'isMac'
35. [warning] prefer-useReducer — apps/terminal/src/components/terminal.tsx:156
Component "Terminal" has 22 useState calls - consider useReducer for related state
36. [warning] rerender-state-only-in-handlers — apps/terminal/src/components/terminal.tsx:182
useState "searchOpenAttempt" is updated but never read in the component's return - use useRef so updates don't trigger re-renders
37. [warning] rerender-state-only-in-handlers — apps/terminal/src/components/terminal.tsx:196
useState "previewFontId" is updated but never read in the component's return - use useRef so updates don't trigger re-renders
38. [warning] rerender-state-only-in-handlers — apps/terminal/src/components/terminal.tsx:207
useState "previewCursorStyle" is updated but never read in the component's return - use useRef so updates don't trigger re-renders
39. [warning] no-giant-component — apps/terminal/src/components/terminal.tsx:156
Component "Terminal" is 1003 lines - consider breaking it into smaller focused components
40. [warning] no-prop-callback-in-effect — apps/terminal/src/components/terminal.tsx:930
useEffect calls prop callback "onModalOpenChange" with local state in deps - this is the "lift state via callback" anti-pattern; lift state into a shared Provider so both sides read the same source
41. [warning] advanced-use-latest — apps/terminal/src/components/terminal.tsx:931
"onModalOpenChange" in effect deps looks like a callback prop - wrap it with useEffectEvent/useLatest and call the latest ref from the subscription instead of re-subscribing
42. [warning] effect-no-pass-data-to-parent — apps/terminal/src/components/terminal.tsx:930
effect passes child-owned data "isModalOpen" to parent callback "onModalOpenChange" - move the data ownership to the parent instead
43. [warning] client-event-listeners — apps/terminal/src/app.tsx:12
global event listener is registered per component instance - share it through a module-level subscription or useSWRSubscription so N components don't add N listeners
44. [warning] client-event-listeners — apps/terminal/src/app.tsx:13
global event listener is registered per component instance - share it through a module-level subscription or useSWRSubscription so N components don't add N listeners
❌ Errors (1)
effect-needs-cleanup
useEffect subscribes via addEventListener(...) but never returns a cleanup - leaks the registration on every re-run and on unmount. Return a cleanup function that calls the matching remove/unsubscribe call
Return cleanup from effects that register timers, subscriptions, listeners, observers, or async resources.
apps/terminal/src/components/terminal.tsx:221
⚠️ Warnings (43)
unused-type-export
The exported symbol "WebErrorCode" is not referenced by reachable modules.
Remove the export or make it part of an entrypoint API.
apps/terminal/src/lib/errors.ts:52
apps/terminal/src/lib/errors.ts:53
apps/terminal/src/lib/local-fonts-types.ts:1
apps/terminal/src/lib/terminal-themes.ts:3
apps/terminal/src/utils/restore-terminal-scroll-anchor.ts:6
runtime-dev-dependency
"react-grab" is imported by runtime code but listed in devDependencies.
Update the nearest package.json dependency bucket to match actual usage.
apps/terminal/src/main.tsx:2
apps/terminal/vite.config.ts:2
apps/terminal/vite.config.ts:3
apps/terminal/vite.config.ts:4
barrel-hotspot
This module exports 61 symbols and is imported by 43 modules.
Prefer direct imports when the barrel inflates the dependency graph.
apps/terminal/src/lib/constants.ts:0
apps/terminal/src/lib/terminal-fonts.ts:0
apps/terminal/src/utils/favicon-state-store.ts:0
rerender-state-only-in-handlers
useState "searchOpenAttempt" is updated but never read in the component's return - use useRef so updates don't trigger re-renders
Avoid subscribing render to state that is only needed inside callbacks; read it on demand or store the transient value in a ref.
apps/terminal/src/components/terminal.tsx:182
apps/terminal/src/components/terminal.tsx:196
apps/terminal/src/components/terminal.tsx:207
unused-export
The exported symbol "clientToServerMessageSchema" is not referenced by reachable modules.
Remove the export or make it part of an entrypoint API.
apps/terminal/src/lib/schemas.ts:2
apps/terminal/src/lib/terminal-fonts.ts:18
unlisted-dependency
"@types/vite/client" is referenced by tsconfig.json but not listed in the workspace package.json.
Update the nearest package.json dependency bucket to match actual usage.
apps/terminal/package.json:0
apps/terminal/package.json:0
js-tosorted-immutable
[...array].sort() - use array.toSorted() for immutable sorting (ES2023)
Use toSorted for immutable sorting instead of cloning and mutating arrays with sort.
apps/terminal/src/utils/query-local-fonts.ts:22
apps/terminal/tests/lib/terminal-scrollback.test.ts:11
no-autofocus
The autoFocus attribute is found here, which can cause usability issues for sighted and non-sighted users.
Remove the autoFocus attribute.
apps/terminal/src/components/local-font-picker.tsx:72
apps/terminal/src/components/local-font-picker.tsx:212
effect-no-adjust-state-on-prop-change
state adjusted from a prop-change effect - derive during render or reset state directly while rendering instead of synchronizing after paint
Do not adjust local state from a prop-change effect; either derive the value during render or restructure state so the prop change does not need a synchronizing effect.
apps/terminal/src/components/local-font-picker.tsx:111
apps/terminal/src/components/local-font-picker.tsx:113
client-event-listeners
global event listener is registered per component instance - share it through a module-level subscription or useSWRSubscription so N components don't add N listeners
Share global window/document listeners through one module-level subscription or a shared hook instead of adding one listener per component instance.
apps/terminal/src/app.tsx:12
apps/terminal/src/app.tsx:13
unused-file
This source file is not reachable from any package, framework, test, or support entrypoint.
Remove the file or connect it to a real entrypoint.
apps/terminal/tests/setup.ts:0
unused-dependency
"@xterm/addon-web-fonts" is listed in dependencies but not used.
Update the nearest package.json dependency bucket to match actual usage.
apps/terminal/package.json:0
unused-dev-dependency
"jsdom" is listed in devDependencies but not used.
Update the nearest package.json dependency bucket to match actual usage.
apps/terminal/package.json:0
type-only-dependency
"zod" is only used in type positions.
Update the nearest package.json dependency bucket to match actual usage.
apps/terminal/src/lib/terminal-session-info.ts:1
rerender-memo-before-early-return
useMemo returning JSX runs before an early return - extract the JSX into a memoized child component so the parent bails out before the subtree renders
Move expensive memoized work below early returns by extracting a child component or computing after the bail-out branch.
apps/terminal/src/components/ui/field.tsx:173
rerender-memo
useMemo returns JSX - extract the expensive subtree into a memoized child component so parent early returns and prop equality can skip the work
Extract expensive JSX subtrees into memoized child components so parent renders and early returns can skip their work.
apps/terminal/src/components/ui/field.tsx:173
no-array-index-as-key
Array index "index" used as key - causes bugs when list is reordered or filtered
Use a stable item id for React keys so inserts, deletes, and sorting preserve component state correctly.
apps/terminal/src/components/ui/field.tsx:190
click-events-have-key-events
Enforce a clickable non-interactive element has at least one keyboard event listener.
Visible, non-interactive elements with click handlers must have one of keyup, keydown, or keypress listener.
apps/terminal/src/components/ui/input-group.tsx:48
label-has-associated-control
A form label must be associated with a control.
Either give the label a htmlFor attribute with the id of the associated control, or wrap the label around the control.
apps/terminal/src/components/ui/label.tsx:9
async-defer-await
await blocks the function before an early-return that doesn't use the awaited value - move the await after the synchronous guard so the skip path stays fast
Move awaits into the branch that needs the result so other branches can return without waiting.
apps/terminal/src/components/local-font-picker.tsx:119
exhaustive-deps
React Hook useEffect has a missing dependency: 'isMac'
Either include it or remove the dependency array.
apps/terminal/src/components/terminal.tsx:441
prefer-useReducer
Component "Terminal" has 22 useState calls - consider useReducer for related state
Replace clusters of related useState setters with a reducer so transitions are explicit and multi-field updates happen together.
apps/terminal/src/components/terminal.tsx:156
no-giant-component
Component "Terminal" is 1003 lines - consider breaking it into smaller focused components
Split large components by responsibility into smaller components or hooks so rendering, state, and effects stay local.
apps/terminal/src/components/terminal.tsx:156
no-prop-callback-in-effect
useEffect calls prop callback "onModalOpenChange" with local state in deps - this is the "lift state via callback" anti-pattern; lift state into a shared Provider so both sides read the same source
Wrap callback props with useEffectEvent/useLatest or call them from the originating event so effects do not re-run only because callback identity changed.
apps/terminal/src/components/terminal.tsx:930
advanced-use-latest
"onModalOpenChange" in effect deps looks like a callback prop - wrap it with useEffectEvent/useLatest and call the latest ref from the subscription instead of re-subscribing
Wrap callback props with useEffectEvent or a useLatest ref and call the latest value from subscriptions instead of re-subscribing on every render.
apps/terminal/src/components/terminal.tsx:931
effect-no-pass-data-to-parent
effect passes child-owned data "isModalOpen" to parent callback "onModalOpenChange" - move the data ownership to the parent instead
Do not fetch or derive child-owned data and push it to a parent from an effect; fetch in the parent and pass data down, or return data from the hook.
apps/terminal/src/components/terminal.tsx:930
Last scored May 13, 2026 at 2:13 PM UTC. Maintained by React Review.
Score: 83/100 · 1 error · 43 warnings
Copy as prompt
❌ Errors (1)
effect-needs-cleanupuseEffect subscribes via
addEventListener(...)but never returns a cleanup - leaks the registration on every re-run and on unmount. Return a cleanup function that calls the matching remove/unsubscribe callapps/terminal/src/components/terminal.tsx:221unused-type-exportThe exported symbol "WebErrorCode" is not referenced by reachable modules.
apps/terminal/src/lib/errors.ts:52apps/terminal/src/lib/errors.ts:53apps/terminal/src/lib/local-fonts-types.ts:1apps/terminal/src/lib/terminal-themes.ts:3apps/terminal/src/utils/restore-terminal-scroll-anchor.ts:6runtime-dev-dependency"react-grab" is imported by runtime code but listed in devDependencies.
apps/terminal/src/main.tsx:2apps/terminal/vite.config.ts:2apps/terminal/vite.config.ts:3apps/terminal/vite.config.ts:4barrel-hotspotThis module exports 61 symbols and is imported by 43 modules.
apps/terminal/src/lib/constants.ts:0apps/terminal/src/lib/terminal-fonts.ts:0apps/terminal/src/utils/favicon-state-store.ts:0rerender-state-only-in-handlersuseState "searchOpenAttempt" is updated but never read in the component's return - use useRef so updates don't trigger re-renders
apps/terminal/src/components/terminal.tsx:182apps/terminal/src/components/terminal.tsx:196apps/terminal/src/components/terminal.tsx:207unused-exportThe exported symbol "clientToServerMessageSchema" is not referenced by reachable modules.
apps/terminal/src/lib/schemas.ts:2apps/terminal/src/lib/terminal-fonts.ts:18unlisted-dependency"@types/vite/client" is referenced by tsconfig.json but not listed in the workspace package.json.
apps/terminal/package.json:0apps/terminal/package.json:0js-tosorted-immutable[...array].sort() - use array.toSorted() for immutable sorting (ES2023)
apps/terminal/src/utils/query-local-fonts.ts:22apps/terminal/tests/lib/terminal-scrollback.test.ts:11no-autofocusThe
autoFocusattribute is found here, which can cause usability issues for sighted and non-sighted users.apps/terminal/src/components/local-font-picker.tsx:72apps/terminal/src/components/local-font-picker.tsx:212effect-no-adjust-state-on-prop-changestate adjusted from a prop-change effect - derive during render or reset state directly while rendering instead of synchronizing after paint
apps/terminal/src/components/local-font-picker.tsx:111apps/terminal/src/components/local-font-picker.tsx:113client-event-listenersglobal event listener is registered per component instance - share it through a module-level subscription or useSWRSubscription so N components don't add N listeners
apps/terminal/src/app.tsx:12apps/terminal/src/app.tsx:13unused-fileThis source file is not reachable from any package, framework, test, or support entrypoint.
apps/terminal/tests/setup.ts:0unused-dependency"@xterm/addon-web-fonts" is listed in dependencies but not used.
apps/terminal/package.json:0unused-dev-dependency"jsdom" is listed in devDependencies but not used.
apps/terminal/package.json:0type-only-dependency"zod" is only used in type positions.
apps/terminal/src/lib/terminal-session-info.ts:1rerender-memo-before-early-returnuseMemo returning JSX runs before an early return - extract the JSX into a memoized child component so the parent bails out before the subtree renders
apps/terminal/src/components/ui/field.tsx:173rerender-memouseMemo returns JSX - extract the expensive subtree into a memoized child component so parent early returns and prop equality can skip the work
apps/terminal/src/components/ui/field.tsx:173no-array-index-as-keyArray index "index" used as key - causes bugs when list is reordered or filtered
apps/terminal/src/components/ui/field.tsx:190click-events-have-key-eventsEnforce a clickable non-interactive element has at least one keyboard event listener.
apps/terminal/src/components/ui/input-group.tsx:48label-has-associated-controlA form label must be associated with a control.
apps/terminal/src/components/ui/label.tsx:9async-defer-awaitawait blocks the function before an early-return that doesn't use the awaited value - move the await after the synchronous guard so the skip path stays fast
apps/terminal/src/components/local-font-picker.tsx:119exhaustive-depsReact Hook useEffect has a missing dependency: 'isMac'
apps/terminal/src/components/terminal.tsx:441prefer-useReducerComponent "Terminal" has 22 useState calls - consider useReducer for related state
apps/terminal/src/components/terminal.tsx:156no-giant-componentComponent "Terminal" is 1003 lines - consider breaking it into smaller focused components
apps/terminal/src/components/terminal.tsx:156no-prop-callback-in-effectuseEffect calls prop callback "onModalOpenChange" with local state in deps - this is the "lift state via callback" anti-pattern; lift state into a shared Provider so both sides read the same source
apps/terminal/src/components/terminal.tsx:930advanced-use-latest"onModalOpenChange" in effect deps looks like a callback prop - wrap it with useEffectEvent/useLatest and call the latest ref from the subscription instead of re-subscribing
apps/terminal/src/components/terminal.tsx:931effect-no-pass-data-to-parenteffect passes child-owned data "isModalOpen" to parent callback "onModalOpenChange" - move the data ownership to the parent instead
apps/terminal/src/components/terminal.tsx:930Last scored May 13, 2026 at 2:13 PM UTC. Maintained by React Review.