Skip to content

React Review Audit #1205

Description

@react-doctor

Score: 87/100 · 1 error · 86 warnings

Copy as prompt
Fix the following React Review diagnostics in my codebase.

## Errors (1)

1. [error] jsx-key — packages/admin/src/works/AddPersonWorkModal.jsx:160
   Missing "key" prop for element in iterator.

## Warnings (86)

2. [warning] client-localstorage-no-version — packages/admin/src/blog/CreateOrEdit/Form.test.jsx:51
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

3. [warning] client-localstorage-no-version — packages/admin/src/blog/CreateOrEdit/Form.test.jsx:102
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

4. [warning] client-localstorage-no-version — packages/admin/src/blog/CreateOrEdit/Form.test.jsx:119
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

5. [warning] rendering-usetransition-loading — packages/admin/src/auth/containers/ActivateAccountContainer.jsx:21
   useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

6. [warning] no-cascading-set-state — packages/admin/src/auth/containers/ActivateAccountContainer.jsx:28
   7 setState calls in a single useEffect — consider using useReducer or deriving state

7. [warning] no-derived-useState — packages/admin/src/blog/CreateOrEdit/Form.jsx:15
   useState initialized from prop "post" — if this value should stay in sync with the prop, derive it during render instead

8. [warning] rendering-hydration-mismatch-time — packages/admin/src/works/Detail.jsx:104
   new Date() reachable from JSX renders differently on server vs client — wrap in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional

9. [warning] no-barrel-import — packages/admin/src/chapters/Detail/index.test.jsx:7
   Import from barrel/index file — import directly from the source module for better tree-shaking

10. [warning] prefer-useReducer — packages/admin/src/works/CreatePersonModal.jsx:18
   Component "CreatePersonModal" has 5 useState calls — consider useReducer for related state

11. [warning] rendering-usetransition-loading — packages/admin/src/auth/containers/SignupContainer.jsx:22
   useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

12. [warning] no-many-boolean-props — packages/admin/src/chapters/Detail/PageItemWithThumb.jsx:168
   Component "PageItemWithThumb" takes 4 boolean-like props (isUploaded, isUploading, isDefaultPage…) — consider compound components or explicit variants instead of stacking flags

13. [warning] rendering-usetransition-loading — packages/admin/src/auth/containers/RecoverPasswordContainer.jsx:21
   useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

14. [warning] no-unknown-property — packages/admin/src/chapters/Detail/PageItem.jsx:88
   Unknown property found

15. [warning] no-many-boolean-props — packages/admin/src/chapters/Detail/PageItem.jsx:29
   Component "PagesItem" takes 4 boolean-like props (isUploaded, isUploading, isDefaultPage…) — consider compound components or explicit variants instead of stacking flags

16. [warning] no-array-index-as-key — packages/admin/src/chapters/Detail/PageItem.jsx:63
   Array index "index" used as key — causes bugs when list is reordered or filtered

17. [warning] client-localstorage-no-version — packages/admin/src/works/CreateOrEdit/Form.test.jsx:50
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

18. [warning] client-localstorage-no-version — packages/admin/src/works/CreateOrEdit/Form.test.jsx:97
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

19. [warning] client-localstorage-no-version — packages/admin/src/works/CreateOrEdit/Form.test.jsx:111
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

20. [warning] no-giant-component — packages/admin/src/works/CreateOrEdit/Form.jsx:18
   Component "PostForm" is 369 lines — consider breaking it into smaller focused components

21. [warning] no-derived-useState — packages/admin/src/works/CreateOrEdit/Form.jsx:19
   useState initialized from prop "work" — if this value should stay in sync with the prop, derive it during render instead

22. [warning] rendering-usetransition-loading — packages/admin/src/auth/containers/LoginContainer.jsx:28
   useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

23. [warning] rerender-lazy-state-init — packages/admin/src/chapters/Detail/DropImages.jsx:44
   useState(map()) calls initializer on every render — use useState(() => map()) for lazy initialization

24. [warning] no-derived-useState — packages/admin/src/chapters/Detail/DropImages.jsx:46
   useState initialized from prop "chapter" — if this value should stay in sync with the prop, derive it during render instead

25. [warning] js-combine-iterations — packages/admin/src/chapters/Detail/DropImages.jsx:79
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

26. [warning] js-combine-iterations — packages/admin/src/chapters/Detail/DropImages.jsx:119
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

27. [warning] js-combine-iterations — packages/admin/src/chapters/Detail/DropImages.jsx:142
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

28. [warning] js-combine-iterations — packages/admin/src/chapters/Detail/DropImages.jsx:164
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

29. [warning] js-tosorted-immutable — packages/admin/src/chapters/Detail/DropImages.jsx:238
   [...array].sort() — use array.toSorted() for immutable sorting (ES2023)

30. [warning] rendering-usetransition-loading — packages/admin/src/auth/containers/ChangePasswordContainer.jsx:24
   useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

31. [warning] rerender-memo-with-default-value — packages/admin/src/chapters/Detail/DetailActions.jsx:20
   Default prop value [] creates a new array reference every render — extract to a module-level constant

32. [warning] client-localstorage-no-version — packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:48
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

33. [warning] client-localstorage-no-version — packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:88
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

34. [warning] client-localstorage-no-version — packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:104
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

35. [warning] client-localstorage-no-version — packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:124
   localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

36. [warning] no-derived-useState — packages/admin/src/chapters/CreateOrEdit/ChapterForm.jsx:10
   useState initialized from prop "chapter" — if this value should stay in sync with the prop, derive it during render instead

37. [warning] rerender-functional-setstate — packages/admin/src/registry/RegistryList.jsx:68
   setPage(page - ...) — use functional update to avoid stale closures

38. [warning] rerender-functional-setstate — packages/admin/src/registry/RegistryList.jsx:77
   setPage(page + ...) — use functional update to avoid stale closures

39. [warning] js-combine-iterations — packages/admin/src/works/AWorksList.jsx:116
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

40. [warning] no-barrel-import — packages/admin/src/layout/header/index.test.jsx:5
   Import from barrel/index file — import directly from the source module for better tree-shaking

41. [warning] no-derived-useState — packages/admin/src/layout/header/index.jsx:30
   useState initialized from prop "isThemeLight" — if this value should stay in sync with the prop, derive it during render instead

42. [warning] no-react-dom-deprecated-apis — packages/admin/src/utils/enzyme-actions.js:1
   react-dom/test-utils is removed in React 19. Use `import { act } from 'react'` instead.

43. [warning] no-children-prop — packages/admin/src/layout/header/RouteNavItem.jsx:53
   Avoid passing children using a prop.

44. [warning] js-combine-iterations — packages/admin/src/user/UsersList.jsx:137
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

45. [warning] no-react-dom-deprecated-apis — packages/admin/src/index.jsx:2
   ReactDOM.render is the legacy root API — switch to `import { createRoot } from 'react-dom/client'` and call `createRoot(container).render(...)` (REMOVED in React 19)

46. [warning] no-react-dom-deprecated-apis — packages/admin/src/index.jsx:2
   ReactDOM.hydrate is the legacy SSR API — switch to `import { hydrateRoot } from 'react-dom/client'` and call `hydrateRoot(container, <App />)` (REMOVED in React 19)

47. [warning] no-react19-deprecated-apis — packages/admin/src/common/Image/component.jsx:1
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

48. [warning] no-many-boolean-props — packages/ui/src/MultiSelect/index.tsx:48
   Component "MultiSelect" takes 4 boolean-like props (hasSelectAll, shouldToggleOnHover, isLoading…) — consider compound components or explicit variants instead of stacking flags

49. [warning] no-prop-callback-in-effect — packages/ui/src/MultiSelect/dropdown.tsx:108
   useEffect calls prop callback "onMenuToggle" 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

50. [warning] no-generic-handler-names — packages/ui/src/MultiSelect/dropdown.tsx:147
   Non-descriptive handler name "handleFocus" — name should describe what it does, not when it runs

51. [warning] no-generic-handler-names — packages/ui/src/MultiSelect/dropdown.tsx:148
   Non-descriptive handler name "handleBlur" — name should describe what it does, not when it runs

52. [warning] no-generic-handler-names — packages/ui/src/select-panel/select-item.tsx:99
   Non-descriptive handler name "handleClick" — name should describe what it does, not when it runs

53. [warning] no-autofocus — packages/ui/src/select-panel/index.tsx:159
   The `autoFocus` attribute is found here, which can cause usability issues for sighted and non-sighted users.

54. [warning] no-derived-state-effect — packages/ui/src/select-panel/index.tsx:90
   Derived state in useEffect — wrap the calculation in useMemo([deps]) (or compute it directly during render if it isn't expensive)

55. [warning] js-combine-iterations — packages/ui/src/select-panel/fuzzy-match-utils.ts:21
   .map().filter() iterates the array twice — combine into a single loop with .reduce() or for...of

56. [warning] js-combine-iterations — packages/ui/src/select-panel/fuzzy-match-utils.ts:21
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

57. [warning] react-compiler-destructure-method — packages/web/src/components/Read/BottomActions.js:47
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

58. [warning] react-compiler-destructure-method — packages/web/src/components/Read/BottomActions.js:57
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

59. [warning] react-compiler-destructure-method — packages/web/src/components/Read/BottomActions.js:74
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

60. [warning] no-react-dom-deprecated-apis — packages/web/src/utils/enzyme-actions.js:1
   react-dom/test-utils is removed in React 19. Use `import { act } from 'react'` instead.

61. [warning] no-array-index-as-key — packages/web/src/components/ComicSlide/ComicSlide.js:55
   Array index "index" used as key — causes bugs when list is reordered or filtered

62. [warning] no-array-index-as-key — packages/web/src/components/ComicSlide/Block.js:46
   Array index "index" used as key — causes bugs when list is reordered or filtered

63. [warning] js-combine-iterations — packages/web/src/pages/work/[lang]/[slug].js:144
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

64. [warning] js-combine-iterations — packages/web/src/pages/work/[lang]/[slug].js:156
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

65. [warning] no-barrel-import — packages/web/src/__tests__/index.js:4
   Import from barrel/index file — import directly from the source module for better tree-shaking

66. [warning] rerender-memo-with-default-value — packages/web/src/pages/releases.js:50
   Default prop value [] creates a new array reference every render — extract to a module-level constant

67. [warning] anchor-is-valid — packages/web/src/__tests__/components/main.test.js:7
   Missing `href` attribute for the `a` element.

68. [warning] react-compiler-destructure-method — packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:125
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

69. [warning] react-compiler-destructure-method — packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:151
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

70. [warning] anchor-is-valid — packages/web/src/__tests__/components/layout/header.test.js:8
   Missing `href` attribute for the `a` element.

71. [warning] design-no-three-period-ellipsis — packages/web/src/pages/blog/[slug].js:41
   Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `&hellip;`)

72. [warning] no-react19-deprecated-apis — packages/web/src/components/Image/component.js:1
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

73. [warning] react-compiler-destructure-method — packages/web/src/components/Blog/PostCard.js:28
   Destructure for clarity: `const { push } = useRouter()` then call `push(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on

74. [warning] no-dynamic-import-path — packages/web/src/pages/_app.js:131
   Template literal with interpolation in require() — use a string literal so the bundler can trace this dependency

75. [warning] no-unknown-property — packages/web/src/components/DiscordWidget/DiscordWidget.js:12
   Unknown property found

76. [warning] no-array-index-as-key — packages/web/src/components/Works/WorksListLoading.js:7
   Array index "index" used as key — causes bugs when list is reordered or filtered

77. [warning] anchor-is-valid — packages/web/src/__tests__/components/ActiveLink.test.js:22
   Missing `href` attribute for the `a` element.

78. [warning] anchor-is-valid — packages/web/src/__tests__/components/ActiveLink.test.js:34
   Missing `href` attribute for the `a` element.

79. [warning] js-combine-iterations — packages/web/src/components/Works/WorksList.js:15
   .filter().forEach() iterates the array twice — combine into a single loop with .reduce() or for...of

80. [warning] client-passive-event-listeners — packages/web/src/hooks/useInfiniteScroll.js:8
   "scroll" listener without { passive: true } — blocks scrolling performance. Only add { passive: true } if the handler does NOT call event.preventDefault() (passive listeners silently ignore preventDefault())

81. [warning] anchor-is-valid — packages/web/src/components/Releases/ReleaseItem.js:71
   Missing `href` attribute for the `a` element.

82. [warning] rerender-lazy-state-init — packages/web/src/hooks/useChapterSeen.js:11
   useState(includes()) calls initializer on every render — use useState(() => includes()) for lazy initialization

83. [warning] no-react19-deprecated-apis — packages/web/src/hooks/use-intl-context.js:1
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

84. [warning] rerender-functional-setstate — packages/web/src/components/Read/ReaderSettings.js:20
   setDisplaySettings({ ...displaySettings, ... }) — use functional update `setDisplaySettings(prev => ({ ...prev, ... }))` to avoid stale closures

85. [warning] anchor-is-valid — packages/web/src/components/Read/ReaderLoading.js:30
   Missing `href` attribute for the `a` element.

86. [warning] anchor-is-valid — packages/web/src/components/Read/ReaderControls.js:63
   Missing `href` attribute for the `a` element.

87. [warning] no-derived-state-effect — packages/web/src/components/Read/ReaderControls.js:47
   State reset in useEffect — use a key prop to reset component state when props change

❌ Errors (1)

jsx-key

Missing "key" prop for element in iterator.

Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key).

packages/admin/src/works/AddPersonWorkModal.jsx:160


⚠️ Warnings (86)

js-combine-iterations

.filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

Combine .map().filter() (or similar chains) into a single pass with .reduce() or a for...of loop to avoid iterating the array twice

packages/admin/src/chapters/Detail/DropImages.jsx:79
packages/admin/src/chapters/Detail/DropImages.jsx:119
packages/admin/src/chapters/Detail/DropImages.jsx:142
packages/admin/src/chapters/Detail/DropImages.jsx:164
packages/admin/src/works/AWorksList.jsx:116
packages/admin/src/user/UsersList.jsx:137
packages/ui/src/select-panel/fuzzy-match-utils.ts:21
packages/ui/src/select-panel/fuzzy-match-utils.ts:21
packages/web/src/pages/work/[lang]/[slug].js:144
packages/web/src/pages/work/[lang]/[slug].js:156
packages/web/src/components/Works/WorksList.js:15

client-localstorage-no-version

localStorage.setItem("user", JSON.stringify(...)) — bake a version into the key (e.g. "user:v1") so a future schema change can ignore old data instead of crashing on it

Bake a version into the storage key (e.g. "myKey:v1"); a future schema change can ignore old data instead of crashing on it

packages/admin/src/blog/CreateOrEdit/Form.test.jsx:51
packages/admin/src/blog/CreateOrEdit/Form.test.jsx:102
packages/admin/src/blog/CreateOrEdit/Form.test.jsx:119
packages/admin/src/works/CreateOrEdit/Form.test.jsx:50
packages/admin/src/works/CreateOrEdit/Form.test.jsx:97
packages/admin/src/works/CreateOrEdit/Form.test.jsx:111
packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:48
packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:88
packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:104
packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:124

anchor-is-valid

Missing href attribute for the a element.

Provide the href attribute for the a element.

packages/web/src/__tests__/components/main.test.js:7
packages/web/src/__tests__/components/layout/header.test.js:8
packages/web/src/__tests__/components/ActiveLink.test.js:22
packages/web/src/__tests__/components/ActiveLink.test.js:34
packages/web/src/components/Releases/ReleaseItem.js:71
packages/web/src/components/Read/ReaderLoading.js:30
packages/web/src/components/Read/ReaderControls.js:63

react-compiler-destructure-method

Destructure for clarity: const { push } = useRouter() then call push(...) directly — easier for React Compiler to memoize and clearer about which methods this component depends on

Destructure the method up front: const { push } = useRouter() then call push(...) directly — clearer dependency graph and easier for React Compiler to memoize

packages/web/src/components/Read/BottomActions.js:47
packages/web/src/components/Read/BottomActions.js:57
packages/web/src/components/Read/BottomActions.js:74
packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:125
packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:151
packages/web/src/components/Blog/PostCard.js:28

rendering-usetransition-loading

useState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead

Replace with const [isPending, startTransition] = useTransition() — avoids a re-render for the loading state

packages/admin/src/auth/containers/ActivateAccountContainer.jsx:21
packages/admin/src/auth/containers/SignupContainer.jsx:22
packages/admin/src/auth/containers/RecoverPasswordContainer.jsx:21
packages/admin/src/auth/containers/LoginContainer.jsx:28
packages/admin/src/auth/containers/ChangePasswordContainer.jsx:24

no-derived-useState

useState initialized from prop "post" — if this value should stay in sync with the prop, derive it during render instead

Remove useState and compute the value inline: const value = transform(propName)

packages/admin/src/blog/CreateOrEdit/Form.jsx:15
packages/admin/src/works/CreateOrEdit/Form.jsx:19
packages/admin/src/chapters/Detail/DropImages.jsx:46
packages/admin/src/chapters/CreateOrEdit/ChapterForm.jsx:10
packages/admin/src/layout/header/index.jsx:30

no-array-index-as-key

Array index "index" used as key — causes bugs when list is reordered or filtered

Use a stable unique identifier: key={item.id} or key={item.slug} — index keys break on reorder/filter

packages/admin/src/chapters/Detail/PageItem.jsx:63
packages/web/src/components/ComicSlide/ComicSlide.js:55
packages/web/src/components/ComicSlide/Block.js:46
packages/web/src/components/Works/WorksListLoading.js:7

no-react-dom-deprecated-apis

react-dom/test-utils is removed in React 19. Use import { act } from 'react' instead.

Switch the legacy react-dom root API (render / hydrate / unmountComponentAtNode) to createRoot / hydrateRoot / root.unmount() from react-dom/client. Replace findDOMNode with a ref. The whole react-dom/test-utils entry point is removed in React 19 — use act from react and fireEvent / render from @testing-library/react. Only enabled on projects detected as React 18+.

packages/admin/src/utils/enzyme-actions.js:1
packages/admin/src/index.jsx:2
packages/admin/src/index.jsx:2
packages/web/src/utils/enzyme-actions.js:1

no-barrel-import

Import from barrel/index file — import directly from the source module for better tree-shaking

Import from the direct path: import { Button } from './components/Button' instead of ./components

packages/admin/src/chapters/Detail/index.test.jsx:7
packages/admin/src/layout/header/index.test.jsx:5
packages/web/src/__tests__/index.js:4

no-many-boolean-props

Component "PageItemWithThumb" takes 4 boolean-like props (isUploaded, isUploading, isDefaultPage…) — consider compound components or explicit variants instead of stacking flags

Split into compound components or named variants: &lt;Button.Primary /&gt;, &lt;DialogConfirm /&gt; instead of stacking isPrimary, isConfirm flags

packages/admin/src/chapters/Detail/PageItemWithThumb.jsx:168
packages/admin/src/chapters/Detail/PageItem.jsx:29
packages/ui/src/MultiSelect/index.tsx:48

rerender-functional-setstate

setPage(page - ...) — use functional update to avoid stale closures

Use the callback form: setState(prev =&gt; prev + 1) to always read the latest value

packages/admin/src/registry/RegistryList.jsx:68
packages/admin/src/registry/RegistryList.jsx:77
packages/web/src/components/Read/ReaderSettings.js:20

no-react19-deprecated-apis

forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

Pass ref as a regular prop on function components — forwardRef is no longer needed in React 19+. Replace useContext(X) with use(X) for branch-aware context reads. Only enabled on projects detected as React 19+.

packages/admin/src/common/Image/component.jsx:1
packages/web/src/components/Image/component.js:1
packages/web/src/hooks/use-intl-context.js:1

no-generic-handler-names

Non-descriptive handler name "handleFocus" — name should describe what it does, not when it runs

Rename to describe the action: e.g. handleSubmitsaveUserProfile, handleClicktoggleSidebar

packages/ui/src/MultiSelect/dropdown.tsx:147
packages/ui/src/MultiSelect/dropdown.tsx:148
packages/ui/src/select-panel/select-item.tsx:99

no-unknown-property

Unknown property found

Remove unknown property

packages/admin/src/chapters/Detail/PageItem.jsx:88
packages/web/src/components/DiscordWidget/DiscordWidget.js:12

rerender-lazy-state-init

useState(map()) calls initializer on every render — use useState(() => map()) for lazy initialization

Wrap in an arrow function so it only runs once: useState(() =&gt; expensiveComputation())

packages/admin/src/chapters/Detail/DropImages.jsx:44
packages/web/src/hooks/useChapterSeen.js:11

rerender-memo-with-default-value

Default prop value [] creates a new array reference every render — extract to a module-level constant

Move to module scope: const EMPTY_ITEMS: Item[] = [] then use as the default value

packages/admin/src/chapters/Detail/DetailActions.jsx:20
packages/web/src/pages/releases.js:50

no-derived-state-effect

Derived state in useEffect — wrap the calculation in useMemo([deps]) (or compute it directly during render if it isn't expensive)

For derived state, compute inline: const x = fn(dep). For state resets on prop change, use a key prop: &lt;Component key={prop} /&gt;. See https://react.dev/learn/you-might-not-need-an-effect

packages/ui/src/select-panel/index.tsx:90
packages/web/src/components/Read/ReaderControls.js:47

no-cascading-set-state

7 setState calls in a single useEffect — consider using useReducer or deriving state

Combine into useReducer: const [state, dispatch] = useReducer(reducer, initialState)

packages/admin/src/auth/containers/ActivateAccountContainer.jsx:28

rendering-hydration-mismatch-time

new Date() reachable from JSX renders differently on server vs client — wrap in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional

Wrap dynamic time/random values in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional

packages/admin/src/works/Detail.jsx:104

prefer-useReducer

Component "CreatePersonModal" has 5 useState calls — consider useReducer for related state

Group related state: const [state, dispatch] = useReducer(reducer, { field1, field2, ... })

packages/admin/src/works/CreatePersonModal.jsx:18

no-giant-component

Component "PostForm" is 369 lines — consider breaking it into smaller focused components

Extract logical sections into focused components: &lt;UserHeader /&gt;, &lt;UserActions /&gt;, etc.

packages/admin/src/works/CreateOrEdit/Form.jsx:18

js-tosorted-immutable

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use array.toSorted() (ES2023) instead of [...array].sort() for immutable sorting without the spread allocation

packages/admin/src/chapters/Detail/DropImages.jsx:238

no-children-prop

Avoid passing children using a prop.

The canonical way to pass children in React is to use JSX elements

packages/admin/src/layout/header/RouteNavItem.jsx:53

no-prop-callback-in-effect

useEffect calls prop callback "onMenuToggle" 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

Lift the shared state into a Provider so both sides read the same source — no useEffect-driven sync needed

packages/ui/src/MultiSelect/dropdown.tsx:108

no-autofocus

The autoFocus attribute is found here, which can cause usability issues for sighted and non-sighted users.

Remove the autoFocus attribute.

packages/ui/src/select-panel/index.tsx:159

design-no-three-period-ellipsis

Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or &hellip;)

Use the typographic ellipsis "…" (or &hellip;) instead of three periods — pairs with action-with-followup labels ("Rename…", "Loading…")

packages/web/src/pages/blog/[slug].js:41

no-dynamic-import-path

Template literal with interpolation in require() — use a string literal so the bundler can trace this dependency

Use a string-literal path: import('./feature/heavy.js') so the bundler can split this chunk

packages/web/src/pages/_app.js:131

client-passive-event-listeners

"scroll" listener without { passive: true } — blocks scrolling performance. Only add { passive: true } if the handler does NOT call event.preventDefault() (passive listeners silently ignore preventDefault())

Add { passive: true } as the third argument: addEventListener('scroll', handler, { passive: true }). Only do this if the handler does NOT call event.preventDefault() — passive listeners silently ignore preventDefault(), which breaks features like pull-to-refresh suppression, custom gestures, and nested-scroll containment.

packages/web/src/hooks/useInfiniteScroll.js:8


Last scored May 13, 2026 at 8:03 PM UTC. Maintained by React Review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions