React Review Audit
Author: react-doctor[bot]Created May 20, 2026Updated May 20, 2026
| ❌ 27 errors, ⚠️ 455 warnings |
Fix the following React Review diagnostics in my codebase.
## Errors (27)
1. [error] effect-needs-cleanup — packages/kitchen-sink/src/examples/interactive-card-game.tsx:67
useEffect schedules `setTimeout(...)` but never returns a cleanup — leaks the registration on every re-run and on unmount. Return a cleanup function that calls clearTimeout(...)
2. [error] jsx-key — packages/kitchen-sink/src/examples/news-aggregator.tsx:88
Missing "key" prop for element in iterator.
3. [error] alt-text — packages/kitchen-sink/src/examples/music-player.jsx:42
Missing `alt` attribute.
4. [error] jsx-key — packages/kitchen-sink/src/examples/snake-game.jsx:7
Missing "key" prop for element in iterator.
5. [error] no-mutable-in-deps — packages/react/for.ts:74
"ref.current" in deps — refs are mutable and don't trigger re-renders, so React won't re-run this effect when it changes. Read the ref inside the effect body instead
6. [error] rules-of-hooks — website/theme.config.tsx:194
React Hook "useRouter" is called in function "Anonymous" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".
7. [error] rules-of-hooks — website/theme.config.tsx:197
React Hook "useConfig" is called in function "Anonymous" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".
8. [error] jsx-key — website/components/extra-content.tsx:74
Missing "key" prop for element in iterator.
9. [error] jsx-key — website/components/extra-content.tsx:76
Missing "key" prop for element in iterator.
10. [error] no-nested-component-definition — website/components/extra-content.tsx:70
Component "Component" defined inside "Showdown" — creates new instance every render, destroying state
11. [error] effect-needs-cleanup — website/components/extra-content.tsx:109
useEffect schedules `setTimeout(...)` but never returns a cleanup — leaks the registration on every re-run and on unmount. Return a cleanup function that calls clearTimeout(...)
12. [error] jsx-key — website/components/back-in-block/vdom.tsx:5
Missing "key" prop for element in array.
13. [error] jsx-key — website/components/back-in-block/vdom.tsx:190
Missing "key" prop for element in array.
14. [error] jsx-key — website/components/back-in-block/vdom.tsx:385
Missing "key" prop for element in array.
15. [error] jsx-key — website/components/back-in-block/vdom.tsx:644
Missing "key" prop for element in array.
16. [error] jsx-key — website/components/back-in-block/vdom.tsx:927
Missing "key" prop for element in array.
17. [error] jsx-key — website/components/back-in-block/vdom.tsx:1228
Missing "key" prop for element in array.
18. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:5
Missing "key" prop for element in array.
19. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:106
Missing "key" prop for element in array.
20. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:210
Missing "key" prop for element in array.
21. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:314
Missing "key" prop for element in array.
22. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:474
Missing "key" prop for element in array.
23. [error] jsx-key — website/components/back-in-block/static-analysis.tsx:659
Missing "key" prop for element in array.
24. [error] alt-text — website/pages/api/og.tsx:115
Missing `alt` attribute.
25. [error] jsx-key — website/components/back-in-block/block-vdom.tsx:5
Missing "key" prop for element in array.
26. [error] jsx-key — website/components/back-in-block/block-vdom.tsx:235
Missing "key" prop for element in array.
27. [error] jsx-key — website/components/back-in-block/block-vdom.tsx:539
Missing "key" prop for element in array.
## Warnings (455)
28. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/calculator.tsx:141
setValue(value / ...) — use functional update to avoid stale closures
29. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/calculator.tsx:145
setValue(value * ...) — use functional update to avoid stale closures
30. [warning] no-array-index-as-key — packages/kitchen-sink/src/examples/calculator.tsx:278
Array index "index" used as key — causes bugs when list is reordered or filtered
31. [warning] rendering-usetransition-loading — packages/kitchen-sink/src/examples/movie-finder.tsx:13
useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead
32. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/counter.tsx:7
setCount(count + ...) — use functional update to avoid stale closures
33. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/password-generator.tsx:74
A form label must be associated with a control.
34. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:64
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
35. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:78
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
36. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:97
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
37. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:111
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
38. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:173
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
39. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:176
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
40. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/password-generator.tsx:212
setPassword({ ...password, ... }) — use functional update `setPassword(prev => ({ ...prev, ... }))` to avoid stale closures
41. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/number-guessing.tsx:19
setAttempts(attempts + ...) — use functional update to avoid stale closures
42. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/guestbook.tsx:28
setComments([...comments, ...]) — use functional update `setComments(prev => [...prev, ...])` to avoid stale closures
43. [warning] design-no-vague-button-label — packages/kitchen-sink/src/examples/guestbook.tsx:49
Vague button label "Submit" — name the action ("Save changes", "Send invite", "Delete account") so screen readers and hesitant users know what happens
44. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/data-converter.tsx:34
setState({ ...state, ... }) — use functional update `setState(prev => ({ ...prev, ... }))` to avoid stale closures
45. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/data-converter.tsx:40
setState({ ...state, ... }) — use functional update `setState(prev => ({ ...prev, ... }))` to avoid stale closures
46. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/data-converter.tsx:46
setState({ ...state, ... }) — use functional update `setState(prev => ({ ...prev, ... }))` to avoid stale closures
47. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/data-converter.tsx:50
setState({ ...state, ... }) — use functional update `setState(prev => ({ ...prev, ... }))` to avoid stale closures
48. [warning] no-inline-exhaustive-style — packages/kitchen-sink/src/examples/data-converter.tsx:75
8 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
49. [warning] no-outline-none — packages/kitchen-sink/src/examples/data-converter.tsx:79
outline: none removes keyboard focus visibility — use :focus-visible styling instead, or provide a box-shadow focus ring
50. [warning] no-inline-exhaustive-style — packages/kitchen-sink/src/examples/data-converter.tsx:110
8 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
51. [warning] no-outline-none — packages/kitchen-sink/src/examples/data-converter.tsx:114
outline: none removes keyboard focus visibility — use :focus-visible styling instead, or provide a box-shadow focus ring
52. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/repro.tsx:17
A form label must have accessible text.
53. [warning] design-no-vague-button-label — packages/kitchen-sink/src/examples/form.tsx:12
Vague button label "Submit" — name the action ("Save changes", "Send invite", "Delete account") so screen readers and hesitant users know what happens
54. [warning] no-unknown-property — packages/kitchen-sink/src/examples/million-quiz.jsx:310
Unknown property found
55. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/million-quiz.jsx:366
Enforce a clickable non-interactive element has at least one keyboard event listener.
56. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/million-quiz.jsx:366
Static HTML elements with event handlers require a role.
57. [warning] design-no-three-period-ellipsis — packages/kitchen-sink/src/examples/million-quiz.jsx:304
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
58. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/styled-counter.tsx:19
setCount(count + ...) — use functional update to avoid stale closures
59. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/interactive-card-game.tsx:30
Enforce a clickable non-interactive element has at least one keyboard event listener.
60. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/interactive-card-game.tsx:30
Static HTML elements with event handlers require a role.
61. [warning] prefer-useReducer — packages/kitchen-sink/src/examples/interactive-card-game.tsx:41
Component "CardGame" has 8 useState calls — consider useReducer for related state
62. [warning] rerender-state-only-in-handlers — packages/kitchen-sink/src/examples/interactive-card-game.tsx:43
useState "selectedCards" is updated but never read in the component's return — use useRef so updates don't trigger re-renders
63. [warning] rerender-state-only-in-handlers — packages/kitchen-sink/src/examples/interactive-card-game.tsx:47
useState "isTimerRunning" is updated but never read in the component's return — use useRef so updates don't trigger re-renders
64. [warning] rerender-lazy-state-init — packages/kitchen-sink/src/examples/interactive-card-game.tsx:42
useState(generateDeck()) calls initializer on every render — use useState(() => generateDeck()) for lazy initialization
65. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/interactive-card-game.tsx:89
setSelectedCards([...selectedCards, ...]) — use functional update `setSelectedCards(prev => [...prev, ...])` to avoid stale closures
66. [warning] no-array-index-as-key — packages/kitchen-sink/src/examples/interactive-card-game.tsx:147
Array index "index" used as key — causes bugs when list is reordered or filtered
67. [warning] no-fetch-in-effect — packages/kitchen-sink/src/examples/crypto-tracker.jsx:72
fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component
68. [warning] no-generic-handler-names — packages/kitchen-sink/src/examples/crypto-tracker.jsx:123
Non-descriptive handler name "handleChange" — name should describe what it does, not when it runs
69. [warning] no-inline-exhaustive-style — packages/kitchen-sink/src/examples/crypto-tracker.jsx:124
9 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
70. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:200
Enforce a clickable non-interactive element has at least one keyboard event listener.
71. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:206
Enforce a clickable non-interactive element has at least one keyboard event listener.
72. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:217
Enforce a clickable non-interactive element has at least one keyboard event listener.
73. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:309
Enforce a clickable non-interactive element has at least one keyboard event listener.
74. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:312
Enforce a clickable non-interactive element has at least one keyboard event listener.
75. [warning] click-events-have-key-events — packages/kitchen-sink/src/examples/task-tracker.tsx:321
Enforce a clickable non-interactive element has at least one keyboard event listener.
76. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:200
Static HTML elements with event handlers require a role.
77. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:206
Static HTML elements with event handlers require a role.
78. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:217
Static HTML elements with event handlers require a role.
79. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:309
Static HTML elements with event handlers require a role.
80. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:312
Static HTML elements with event handlers require a role.
81. [warning] no-static-element-interactions — packages/kitchen-sink/src/examples/task-tracker.tsx:321
Static HTML elements with event handlers require a role.
82. [warning] no-derived-useState — packages/kitchen-sink/src/examples/task-tracker.tsx:140
useState initialized from prop "itemData" — if this value should stay in sync with the prop, derive it during render instead
83. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/task-tracker.tsx:142
setItem({ ...item, ... }) — use functional update `setItem(prev => ({ ...prev, ... }))` to avoid stale closures
84. [warning] no-inline-exhaustive-style — packages/kitchen-sink/src/examples/task-tracker.tsx:260
8 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
85. [warning] no-array-index-as-key — packages/kitchen-sink/src/examples/task-tracker.tsx:419
Array index "index" used as key — causes bugs when list is reordered or filtered
86. [warning] no-cascading-set-state — packages/kitchen-sink/src/examples/location-app.tsx:9
4 setState calls in a single useEffect — consider using useReducer or deriving state
87. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/digital-personal-journal.jsx:66
setEntries([...entries, ...]) — use functional update `setEntries(prev => [...prev, ...])` to avoid stale closures
88. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/digital-personal-journal.jsx:67
setNextId(nextId + ...) — use functional update to avoid stale closures
89. [warning] no-inline-exhaustive-style — packages/kitchen-sink/src/examples/digital-personal-journal.jsx:106
10 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
90. [warning] no-cascading-set-state — packages/kitchen-sink/src/examples/type-race.jsx:94
3 setState calls in a single useEffect — consider using useReducer or deriving state
91. [warning] prefer-useReducer — packages/kitchen-sink/src/examples/type-race.jsx:164
Component "TypeRace" has 9 useState calls — consider useReducer for related state
92. [warning] rerender-state-only-in-handlers — packages/kitchen-sink/src/examples/type-race.jsx:171
useState "timeLap" is updated but never read in the component's return — use useRef so updates don't trigger re-renders
93. [warning] rerender-functional-setstate — packages/kitchen-sink/src/examples/type-race.jsx:200
setTotalChar(totalChar + ...) — use functional update to avoid stale closures
94. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/mortgage-calculator.tsx:42
A form label must be associated with a control.
95. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/mortgage-calculator.tsx:51
A form label must be associated with a control.
96. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/mortgage-calculator.tsx:60
A form label must be associated with a control.
97. [warning] anchor-is-valid — packages/kitchen-sink/src/examples/wouter.tsx:7
Missing `href` attribute for the `a` element.
98. [warning] no-secrets-in-client-code — packages/kitchen-sink/src/examples/news-aggregator.tsx:24
Possible hardcoded secret in "apikey" — use environment variables instead
99. [warning] no-cascading-set-state — packages/kitchen-sink/src/examples/news-aggregator.tsx:69
3 setState calls in a single useEffect — consider using useReducer or deriving state
100. [warning] no-fetch-in-effect — packages/kitchen-sink/src/examples/news-aggregator.tsx:69
fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component
101. [warning] design-no-three-period-ellipsis — packages/kitchen-sink/src/examples/news-aggregator.tsx:85
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
102. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/bmi-calculator.jsx:51
A form label must be associated with a control.
103. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/bmi-calculator.jsx:62
A form label must be associated with a control.
104. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/bmi-calculator.jsx:70
A form label must be associated with a control.
105. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/bmi-calculator.jsx:81
A form label must be associated with a control.
106. [warning] label-has-associated-control — packages/kitchen-sink/src/examples/bmi-calculator.jsx:92
A form label must be associated with a control.
107. [warning] no-cascading-set-state — packages/kitchen-sink/src/examples/music-player.jsx:101
3 setState calls in a single useEffect — consider using useReducer or deriving state
108.Source: aidenybai/million