Skip to content

React Review Audit #3

@reactreview

Description

@reactreview

Score: 91/100 · 1 error · 31 warnings

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

## Errors (1)

1. [error] require-reduced-motion — packages/design-system/package.json:0
   Project uses a motion library but has no prefers-reduced-motion handling — required for accessibility (WCAG 2.3.3)

## Warnings (31)

2. [warning] nextjs-missing-metadata — apps/web/app/(home)/page.tsx:1
   Page without metadata or generateMetadata export — hurts SEO

3. [warning] no-danger — packages/design-system/components/ui/chart.tsx:95
   Do not use `dangerouslySetInnerHTML` prop

4. [warning] prefer-dynamic-import — packages/design-system/components/ui/chart.tsx:4
   "recharts" is a heavy library — use React.lazy() or next/dynamic for code splitting

5. [warning] prefer-dynamic-import — packages/design-system/components/ui/chart.tsx:5
   "recharts" is a heavy library — use React.lazy() or next/dynamic for code splitting

6. [warning] no-react19-deprecated-apis — packages/design-system/components/ui/chart.tsx:33
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

7. [warning] rerender-memo-before-early-return — packages/design-system/components/ui/chart.tsx:149
   useMemo returning JSX runs before an early return — extract the JSX into a memoized child component so the parent bails out before the subtree renders

8. [warning] js-combine-iterations — packages/design-system/components/ui/chart.tsx:200
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

9. [warning] no-array-index-as-key — packages/design-system/components/ui/chart.tsx:209
   Array index "index" used as key — causes bugs when list is reordered or filtered

10. [warning] js-combine-iterations — packages/design-system/components/ui/chart.tsx:299
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

11. [warning] no-array-index-as-key — packages/design-system/components/ui/chart.tsx:307
   Array index "index" used as key — causes bugs when list is reordered or filtered

12. [warning] design-no-redundant-size-axes — packages/design-system/components/ui/chart.tsx:316
   w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)

13. [warning] no-react19-deprecated-apis — packages/design-system/components/ui/carousel.tsx:36
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

14. [warning] no-prop-callback-in-effect — packages/design-system/components/ui/carousel.tsx:93
   useEffect calls prop callback "setApi" 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

15. [warning] advanced-event-handler-refs — packages/design-system/components/ui/carousel.tsx:96
   useEffect re-subscribes a "onSelect" listener every time the handler identity changes — store the handler in a ref and have the listener read `handlerRef.current()`, then drop it from the deps

16. [warning] no-react19-deprecated-apis — packages/design-system/components/ui/input-otp.tsx:50
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

17. [warning] click-events-have-key-events — packages/design-system/components/ui/input-group.tsx:52
   Enforce a clickable non-interactive element has at least one keyboard event listener.

18. [warning] no-danger — packages/design-system/components/kibo-ui/code-block/server.tsx:59
   Do not use `dangerouslySetInnerHTML` prop

19. [warning] rerender-memo-before-early-return — packages/design-system/components/ui/field.tsx:184
   useMemo returning JSX runs before an early return — extract the JSX into a memoized child component so the parent bails out before the subtree renders

20. [warning] no-array-index-as-key — packages/design-system/components/ui/field.tsx:205
   Array index "index" used as key — causes bugs when list is reordered or filtered

21. [warning] no-danger — packages/design-system/components/kibo-ui/code-block/index.tsx:634
   Do not use `dangerouslySetInnerHTML` prop

22. [warning] no-react19-deprecated-apis — packages/design-system/components/kibo-ui/code-block/index.tsx:21
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

23. [warning] design-no-redundant-size-axes — packages/design-system/components/kibo-ui/code-block/index.tsx:413
   w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)

24. [warning] rerender-state-only-in-handlers — packages/design-system/components/kibo-ui/code-block/index.tsx:488
   useState "isCopied" is updated but never read in the component's return — use useRef so updates don't trigger re-renders

25. [warning] no-array-index-as-key — packages/design-system/components/kibo-ui/code-block/index.tsx:541
   Array index "i" used as key — causes bugs when list is reordered or filtered

26. [warning] use-lazy-motion — packages/design-system/components/copy-button.tsx:8
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

27. [warning] no-react19-deprecated-apis — packages/design-system/components/ui/toggle-group.tsx:66
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

28. [warning] no-react19-deprecated-apis — packages/design-system/components/ui/sidebar.tsx:47
   useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`

29. [warning] no-derived-useState — packages/design-system/components/ui/sidebar.tsx:73
   useState initialized from prop "defaultOpen" — if this value should stay in sync with the prop, derive it during render instead

30. [warning] no-redundant-roles — packages/design-system/components/ui/pagination.tsx:10
   The `nav` element has an implicit role of `navigation`. Defining this explicitly is redundant and should be avoided.

31. [warning] no-array-index-as-key — packages/design-system/components/ui/slider.tsx:51
   Array index "index" used as key — causes bugs when list is reordered or filtered

32. [warning] design-no-redundant-size-axes — packages/design-system/components/ui/navigation-menu.tsx:149
   w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)

❌ Errors (1)

require-reduced-motion

Project uses a motion library but has no prefers-reduced-motion handling — required for accessibility (WCAG 2.3.3)

Add useReducedMotion() from your animation library, or a @media (prefers-reduced-motion: reduce) CSS query

packages/design-system/package.json:0


⚠️ Warnings (31)

no-react19-deprecated-apis

useContext is superseded by use() on React 19+ — use() reads context conditionally inside hooks, branches, and loops; switch to import { use } from 'react'

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/design-system/components/ui/chart.tsx:33
packages/design-system/components/ui/carousel.tsx:36
packages/design-system/components/ui/input-otp.tsx:50
packages/design-system/components/kibo-ui/code-block/index.tsx:21
packages/design-system/components/ui/toggle-group.tsx:66
packages/design-system/components/ui/sidebar.tsx:47

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/design-system/components/ui/chart.tsx:209
packages/design-system/components/ui/chart.tsx:307
packages/design-system/components/ui/field.tsx:205
packages/design-system/components/kibo-ui/code-block/index.tsx:541
packages/design-system/components/ui/slider.tsx:51

no-danger

Do not use dangerouslySetInnerHTML prop

dangerouslySetInnerHTML is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities.

packages/design-system/components/ui/chart.tsx:95
packages/design-system/components/kibo-ui/code-block/server.tsx:59
packages/design-system/components/kibo-ui/code-block/index.tsx:634

design-no-redundant-size-axes

w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)

Collapse w-N h-N to size-N (Tailwind v3.4+) when both axes match

packages/design-system/components/ui/chart.tsx:316
packages/design-system/components/kibo-ui/code-block/index.tsx:413
packages/design-system/components/ui/navigation-menu.tsx:149

prefer-dynamic-import

"recharts" is a heavy library — use React.lazy() or next/dynamic for code splitting

Use const Component = dynamic(() => import('library'), { ssr: false }) from next/dynamic or React.lazy()

packages/design-system/components/ui/chart.tsx:4
packages/design-system/components/ui/chart.tsx:5

rerender-memo-before-early-return

useMemo returning JSX runs before an early return — extract the JSX into a memoized child component so the parent bails out before the subtree renders

Extract the JSX into a memoized child component so the parent's early return short-circuits before the child renders

packages/design-system/components/ui/chart.tsx:149
packages/design-system/components/ui/field.tsx:184

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/design-system/components/ui/chart.tsx:200
packages/design-system/components/ui/chart.tsx:299

nextjs-missing-metadata

Page without metadata or generateMetadata export — hurts SEO

Add export const metadata = { title: '...', description: '...' } or export async function generateMetadata()

apps/web/app/(home)/page.tsx:1

no-prop-callback-in-effect

useEffect calls prop callback "setApi" 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/design-system/components/ui/carousel.tsx:93

advanced-event-handler-refs

useEffect re-subscribes a "onSelect" listener every time the handler identity changes — store the handler in a ref and have the listener read handlerRef.current(), then drop it from the deps

Store the handler in a ref and have the listener read handlerRef.current() — the subscription stays put while the latest handler is always called

packages/design-system/components/ui/carousel.tsx:96

click-events-have-key-events

Enforce a clickable non-interactive element has at least one keyboard event listener.

Visible, non-interactive elements with click handlers must have one of keyup, keydown, or keypress listener.

packages/design-system/components/ui/input-group.tsx:52

rerender-state-only-in-handlers

useState "isCopied" is updated but never read in the component's return — use useRef so updates don't trigger re-renders

Replace useState with useRef when the value is only mutated and never read in render — ref.current = ... updates without re-rendering the component

packages/design-system/components/kibo-ui/code-block/index.tsx:488

use-lazy-motion

Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

Use import { LazyMotion, m } from "framer-motion" with domAnimation features — saves ~30kb

packages/design-system/components/copy-button.tsx:8

no-derived-useState

useState initialized from prop "defaultOpen" — 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/design-system/components/ui/sidebar.tsx:73

no-redundant-roles

The nav element has an implicit role of navigation. Defining this explicitly is redundant and should be avoided.

Remove the redundant role navigation from the element nav.

packages/design-system/components/ui/pagination.tsx:10


Last scored May 13, 2026 at 7:34 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