#1187·million

React Review Audit

Author: react-doctor[bot]Created May 20, 2026Updated May 20, 2026
27 errors, ⚠️ 455 warnings 78 score
Copy as prompt
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.