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 `…`)
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: <Button.Primary />, <DialogConfirm /> 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 => 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. handleSubmit → saveUserProfile, handleClick → toggleSidebar
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(() => 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: <Component key={prop} />. 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: <UserHeader />, <UserActions />, 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 …)
Use the typographic ellipsis "…" (or …) 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.
Score: 87/100 · 1 error · 86 warnings
Copy as prompt
❌ Errors (1)
jsx-keyMissing "key" prop for element in iterator.
packages/admin/src/works/AddPersonWorkModal.jsx:160js-combine-iterations.filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of
packages/admin/src/chapters/Detail/DropImages.jsx:79packages/admin/src/chapters/Detail/DropImages.jsx:119packages/admin/src/chapters/Detail/DropImages.jsx:142packages/admin/src/chapters/Detail/DropImages.jsx:164packages/admin/src/works/AWorksList.jsx:116packages/admin/src/user/UsersList.jsx:137packages/ui/src/select-panel/fuzzy-match-utils.ts:21packages/ui/src/select-panel/fuzzy-match-utils.ts:21packages/web/src/pages/work/[lang]/[slug].js:144packages/web/src/pages/work/[lang]/[slug].js:156packages/web/src/components/Works/WorksList.js:15client-localstorage-no-versionlocalStorage.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
packages/admin/src/blog/CreateOrEdit/Form.test.jsx:51packages/admin/src/blog/CreateOrEdit/Form.test.jsx:102packages/admin/src/blog/CreateOrEdit/Form.test.jsx:119packages/admin/src/works/CreateOrEdit/Form.test.jsx:50packages/admin/src/works/CreateOrEdit/Form.test.jsx:97packages/admin/src/works/CreateOrEdit/Form.test.jsx:111packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:48packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:88packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:104packages/admin/src/chapters/CreateOrEdit/ChapterForm.test.jsx:124anchor-is-validMissing
hrefattribute for theaelement.packages/web/src/__tests__/components/main.test.js:7packages/web/src/__tests__/components/layout/header.test.js:8packages/web/src/__tests__/components/ActiveLink.test.js:22packages/web/src/__tests__/components/ActiveLink.test.js:34packages/web/src/components/Releases/ReleaseItem.js:71packages/web/src/components/Read/ReaderLoading.js:30packages/web/src/components/Read/ReaderControls.js:63react-compiler-destructure-methodDestructure for clarity:
const { push } = useRouter()then callpush(...)directly — easier for React Compiler to memoize and clearer about which methods this component depends onpackages/web/src/components/Read/BottomActions.js:47packages/web/src/components/Read/BottomActions.js:57packages/web/src/components/Read/BottomActions.js:74packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:125packages/web/src/pages/read/[slug]/[lang]/[volume]/[chapter].js:151packages/web/src/components/Blog/PostCard.js:28rendering-usetransition-loadinguseState for "isLoading" — if this guards a state transition (not an async fetch), consider useTransition instead
packages/admin/src/auth/containers/ActivateAccountContainer.jsx:21packages/admin/src/auth/containers/SignupContainer.jsx:22packages/admin/src/auth/containers/RecoverPasswordContainer.jsx:21packages/admin/src/auth/containers/LoginContainer.jsx:28packages/admin/src/auth/containers/ChangePasswordContainer.jsx:24no-derived-useStateuseState initialized from prop "post" — if this value should stay in sync with the prop, derive it during render instead
packages/admin/src/blog/CreateOrEdit/Form.jsx:15packages/admin/src/works/CreateOrEdit/Form.jsx:19packages/admin/src/chapters/Detail/DropImages.jsx:46packages/admin/src/chapters/CreateOrEdit/ChapterForm.jsx:10packages/admin/src/layout/header/index.jsx:30no-array-index-as-keyArray index "index" used as key — causes bugs when list is reordered or filtered
packages/admin/src/chapters/Detail/PageItem.jsx:63packages/web/src/components/ComicSlide/ComicSlide.js:55packages/web/src/components/ComicSlide/Block.js:46packages/web/src/components/Works/WorksListLoading.js:7no-react-dom-deprecated-apisreact-dom/test-utils is removed in React 19. Use
import { act } from 'react'instead.packages/admin/src/utils/enzyme-actions.js:1packages/admin/src/index.jsx:2packages/admin/src/index.jsx:2packages/web/src/utils/enzyme-actions.js:1no-barrel-importImport from barrel/index file — import directly from the source module for better tree-shaking
packages/admin/src/chapters/Detail/index.test.jsx:7packages/admin/src/layout/header/index.test.jsx:5packages/web/src/__tests__/index.js:4no-many-boolean-propsComponent "PageItemWithThumb" takes 4 boolean-like props (isUploaded, isUploading, isDefaultPage…) — consider compound components or explicit variants instead of stacking flags
packages/admin/src/chapters/Detail/PageItemWithThumb.jsx:168packages/admin/src/chapters/Detail/PageItem.jsx:29packages/ui/src/MultiSelect/index.tsx:48rerender-functional-setstatesetPage(page - ...) — use functional update to avoid stale closures
packages/admin/src/registry/RegistryList.jsx:68packages/admin/src/registry/RegistryList.jsx:77packages/web/src/components/Read/ReaderSettings.js:20no-react19-deprecated-apisforwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
packages/admin/src/common/Image/component.jsx:1packages/web/src/components/Image/component.js:1packages/web/src/hooks/use-intl-context.js:1no-generic-handler-namesNon-descriptive handler name "handleFocus" — name should describe what it does, not when it runs
packages/ui/src/MultiSelect/dropdown.tsx:147packages/ui/src/MultiSelect/dropdown.tsx:148packages/ui/src/select-panel/select-item.tsx:99no-unknown-propertyUnknown property found
packages/admin/src/chapters/Detail/PageItem.jsx:88packages/web/src/components/DiscordWidget/DiscordWidget.js:12rerender-lazy-state-inituseState(map()) calls initializer on every render — use useState(() => map()) for lazy initialization
packages/admin/src/chapters/Detail/DropImages.jsx:44packages/web/src/hooks/useChapterSeen.js:11rerender-memo-with-default-valueDefault prop value [] creates a new array reference every render — extract to a module-level constant
packages/admin/src/chapters/Detail/DetailActions.jsx:20packages/web/src/pages/releases.js:50no-derived-state-effectDerived state in useEffect — wrap the calculation in useMemo([deps]) (or compute it directly during render if it isn't expensive)
packages/ui/src/select-panel/index.tsx:90packages/web/src/components/Read/ReaderControls.js:47no-cascading-set-state7 setState calls in a single useEffect — consider using useReducer or deriving state
packages/admin/src/auth/containers/ActivateAccountContainer.jsx:28rendering-hydration-mismatch-timenew Date() reachable from JSX renders differently on server vs client — wrap in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional
packages/admin/src/works/Detail.jsx:104prefer-useReducerComponent "CreatePersonModal" has 5 useState calls — consider useReducer for related state
packages/admin/src/works/CreatePersonModal.jsx:18no-giant-componentComponent "PostForm" is 369 lines — consider breaking it into smaller focused components
packages/admin/src/works/CreateOrEdit/Form.jsx:18js-tosorted-immutable[...array].sort() — use array.toSorted() for immutable sorting (ES2023)
packages/admin/src/chapters/Detail/DropImages.jsx:238no-children-propAvoid passing children using a prop.
packages/admin/src/layout/header/RouteNavItem.jsx:53no-prop-callback-in-effectuseEffect 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
packages/ui/src/MultiSelect/dropdown.tsx:108no-autofocusThe
autoFocusattribute is found here, which can cause usability issues for sighted and non-sighted users.packages/ui/src/select-panel/index.tsx:159design-no-three-period-ellipsisThree-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or
…)packages/web/src/pages/blog/[slug].js:41no-dynamic-import-pathTemplate literal with interpolation in require() — use a string literal so the bundler can trace this dependency
packages/web/src/pages/_app.js:131client-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())
packages/web/src/hooks/useInfiniteScroll.js:8Last scored May 13, 2026 at 8:03 PM UTC. Maintained by React Review.