Skip to content

React Review Audit #68

Description

@react-doctor
1 error, ⚠️ 120 warnings 79 score
Copy as prompt
Fix the following React Review diagnostics in my codebase.

## Errors (1)

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

## Warnings (120)

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

3. [warning] no-multi-comp — components/ui/alert.tsx:36
   Declare only one React component per file. Found extra component: AlertTitle.

4. [warning] no-multi-comp — components/ui/alert.tsx:48
   Declare only one React component per file. Found extra component: AlertDescription.

5. [warning] no-react19-deprecated-apis — components/ui/alert.tsx:23
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

6. [warning] no-react19-deprecated-apis — components/ui/alert.tsx:36
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

7. [warning] heading-has-content — components/ui/alert.tsx:40
   Heading elements must contain accessible text content (or `aria-label` / `aria-labelledby`).

8. [warning] no-react19-deprecated-apis — components/ui/alert.tsx:48
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

9. [warning] design-no-redundant-size-axes — components/favorites/favorites-page.tsx:52
   w-16 h-16 → use the shorthand size-16 (Tailwind v3.4+)

10. [warning] design-no-redundant-size-axes — components/favorites/favorites-page.tsx:105
   w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)

11. [warning] prefer-tag-over-role — components/shared/resources/custom-card.tsx:46
   Prefer the semantic `<img>` element over `role="img"` on a generic tag.

12. [warning] rendering-svg-precision — app/resources-og/[...slug]/og.tsx:100
   SVG d attribute uses 4+ decimal precision — truncate to 1–2 decimals to shrink markup with no visible difference

13. [warning] no-react19-deprecated-apis — components/ui/card.tsx:5
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

14. [warning] no-react19-deprecated-apis — components/ui/card.tsx:20
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

15. [warning] no-react19-deprecated-apis — components/ui/card.tsx:32
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

16. [warning] heading-has-content — components/ui/card.tsx:36
   Heading elements must contain accessible text content (or `aria-label` / `aria-labelledby`).

17. [warning] no-react19-deprecated-apis — components/ui/card.tsx:44
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

18. [warning] no-react19-deprecated-apis — components/ui/card.tsx:56
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

19. [warning] no-react19-deprecated-apis — components/ui/card.tsx:68
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

20. [warning] use-lazy-motion — components/shared/home/guides-card.tsx:11
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

21. [warning] no-multi-comp — components/ui/avatar.tsx:24
   Declare only one React component per file. Found extra component: AvatarImage.

22. [warning] no-multi-comp — components/ui/avatar.tsx:36
   Declare only one React component per file. Found extra component: AvatarFallback.

23. [warning] no-react19-deprecated-apis — components/ui/avatar.tsx:9
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

24. [warning] no-react19-deprecated-apis — components/ui/avatar.tsx:24
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

25. [warning] no-react19-deprecated-apis — components/ui/avatar.tsx:36
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

26. [warning] no-react19-deprecated-apis — components/ui/input.tsx:5
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

27. [warning] no-react19-deprecated-apis — components/ui/checkbox.tsx:10
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

28. [warning] design-no-redundant-size-axes — components/ui/checkbox.tsx:25
   w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)

29. [warning] use-lazy-motion — components/animate-ui/text/sliding-number.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

30. [warning] no-event-handler — components/animate-ui/text/sliding-number.tsx:134
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

31. [warning] no-event-handler — components/animate-ui/text/sliding-number.tsx:131
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

32. [warning] no-event-handler — components/animate-ui/text/sliding-number.tsx:132
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

33. [warning] no-react19-deprecated-apis — components/ui/scroll-area.tsx:9
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

34. [warning] no-react19-deprecated-apis — components/ui/scroll-area.tsx:27
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

35. [warning] no-react19-deprecated-apis — components/ui/label.tsx:14
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

36. [warning] no-react19-deprecated-apis — components/ui/slider.tsx:9
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

37. [warning] design-no-redundant-size-axes — components/ui/slider.tsx:24
   w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)

38. [warning] no-react19-deprecated-apis — components/ui/separator.tsx:9
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

39. [warning] use-lazy-motion — components/shared/home/hero/hero-image.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

40. [warning] use-lazy-motion — components/animate-ui/github-stars-button.tsx:4
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

41. [warning] prefer-use-effect-event — components/animate-ui/github-stars-button.tsx:118
   "handleDisplayParticles" is read only inside `on` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render

42. [warning] no-usememo-simple-expression — components/animate-ui/github-stars-button.tsx:73
   useMemo wrapping a trivially cheap expression — memo overhead exceeds the computation

43. [warning] no-fetch-in-effect — components/animate-ui/github-stars-button.tsx:78
   fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component

44. [warning] no-event-handler — components/animate-ui/github-stars-button.tsx:121
   Avoid using state and effects as an event handler. Instead, call the event handling code directly when the event occurs.

45. [warning] no-event-handler — components/animate-ui/github-stars-button.tsx:102
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

46. [warning] no-event-handler — components/animate-ui/github-stars-button.tsx:99
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

47. [warning] no-event-handler — components/animate-ui/github-stars-button.tsx:100
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

48. [warning] no-generic-handler-names — components/animate-ui/github-stars-button.tsx:182
   Non-descriptive handler name "handleClick" — name should describe what it does, not when it runs

49. [warning] design-no-redundant-size-axes — components/animate-ui/github-stars-button.tsx:255
   w-1 h-1 → use the shorthand size-1 (Tailwind v3.4+)

50. [warning] no-scale-from-zero — components/animate-ui/github-stars-button.tsx:256
   scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance

51. [warning] no-render-in-render — components/animate-ui/github-stars-button.tsx:275
   Inline render function "renderNumberSegments()" — extract to a separate component for proper reconciliation

52. [warning] no-render-in-render — components/animate-ui/github-stars-button.tsx:280
   Inline render function "renderNumberSegments()" — extract to a separate component for proper reconciliation

53. [warning] no-react19-deprecated-apis — components/ui/table.tsx:5
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

54. [warning] no-react19-deprecated-apis — components/ui/table.tsx:19
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

55. [warning] no-react19-deprecated-apis — components/ui/table.tsx:31
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

56. [warning] no-react19-deprecated-apis — components/ui/table.tsx:43
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

57. [warning] no-react19-deprecated-apis — components/ui/table.tsx:58
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

58. [warning] no-react19-deprecated-apis — components/ui/table.tsx:73
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

59. [warning] no-react19-deprecated-apis — components/ui/table.tsx:88
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

60. [warning] no-react19-deprecated-apis — components/ui/table.tsx:103
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

61. [warning] use-lazy-motion — components/shared/home/section-title.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

62. [warning] js-combine-iterations — lib/favorites.ts:27
   .filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of

63. [warning] rendering-svg-precision — app/guides-og/[...slug]/og.tsx:100
   SVG d attribute uses 4+ decimal precision — truncate to 1–2 decimals to shrink markup with no visible difference

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

65. [warning] jsx-no-constructed-context-values — components/shared/page-context.tsx:19
   Context `value` prop is constructed inline — wrap with `useMemo`/`useCallback` or hoist a constant to avoid re-renders.

66. [warning] use-lazy-motion — components/shared/home/hero/hero-paragraph.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

67. [warning] no-array-index-key — components/shared/mdx-elements.tsx:298
   Array index in `key` doesn't uniquely identify the element — re-renders may use stale state.

68. [warning] no-array-index-as-key — components/shared/mdx-elements.tsx:298
   Array index "index" used as key — causes bugs when list is reordered or filtered

69. [warning] no-array-index-key — components/shared/mdx-elements.tsx:338
   Array index in `key` doesn't uniquely identify the element — re-renders may use stale state.

70. [warning] no-array-index-as-key — components/shared/mdx-elements.tsx:338
   Array index "idx" used as key — causes bugs when list is reordered or filtered

71. [warning] no-array-index-key — components/shared/mdx-elements.tsx:345
   Array index in `key` doesn't uniquely identify the element — re-renders may use stale state.

72. [warning] no-array-index-as-key — components/shared/mdx-elements.tsx:345
   Array index "idx" used as key — causes bugs when list is reordered or filtered

73. [warning] use-lazy-motion — components/shared/home/hero/action-button.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

74. [warning] use-lazy-motion — components/ui/gradual-spacing.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

75. [warning] design-no-space-on-flex-children — components/ui/gradual-spacing.tsx:26
   space-x-1 on a flex/grid parent — use gap-x-1 instead. Per-sibling margins phantom-gap on conditional render and don't mirror in RTL

76. [warning] no-array-index-as-key — components/ui/gradual-spacing.tsx:30
   Array index "i" used as key — causes bugs when list is reordered or filtered

77. [warning] use-lazy-motion — components/animate-ui/buttons/icon.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

78. [warning] no-scale-from-zero — components/animate-ui/buttons/icon.tsx:74
   scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance

79. [warning] no-scale-from-zero — components/animate-ui/buttons/icon.tsx:76
   scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance

80. [warning] design-no-redundant-size-axes — components/animate-ui/buttons/icon.tsx:108
   w-1 h-1 → use the shorthand size-1 (Tailwind v3.4+)

81. [warning] no-scale-from-zero — components/animate-ui/buttons/icon.tsx:109
   scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance

82. [warning] use-lazy-motion — components/shared/home/resources-marquee.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

83. [warning] prefer-tag-over-role — components/shared/home/resources-marquee.tsx:99
   Prefer the semantic `<img>` element over `role="img"` on a generic tag.

84. [warning] prefer-tag-over-role — components/shared/home/resources-marquee.tsx:137
   Prefer the semantic `<img>` element over `role="img"` on a generic tag.

85. [warning] prefer-use-effect-event — components/ui/flickering-grid.tsx:162
   "updateSquares" is read only inside `requestAnimationFrame` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render

86. [warning] prefer-use-effect-event — components/ui/flickering-grid.tsx:162
   "drawGrid" is read only inside `requestAnimationFrame` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render

87. [warning] rerender-state-only-in-handlers — components/ui/flickering-grid.tsx:27
   useState "isInView" is updated but never read in the component's return — use useRef so updates don't trigger re-renders

88. [warning] no-adjust-state-on-prop-change — components/ui/flickering-grid.tsx:149
   Avoid adjusting state when a prop changes. Instead, adjust the state directly during render, or refactor your state to avoid this need entirely.

89. [warning] no-react19-deprecated-apis — components/ui/radio-group.tsx:10
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

90. [warning] no-react19-deprecated-apis — components/ui/radio-group.tsx:24
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

91. [warning] design-no-redundant-size-axes — components/ui/radio-group.tsx:38
   w-3.5 h-3.5 → use the shorthand size-3.5 (Tailwind v3.4+)

92. [warning] no-array-index-as-key — components/ui/marquee.tsx:38
   Array index "i" used as key — causes bugs when list is reordered or filtered

93. [warning] no-react19-deprecated-apis — components/ui/sheet.tsx:19
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

94. [warning] no-react19-deprecated-apis — components/ui/sheet.tsx:57
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

95. [warning] design-no-redundant-size-axes — components/ui/sheet.tsx:69
   w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)

96. [warning] no-react19-deprecated-apis — components/ui/sheet.tsx:106
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

97. [warning] no-react19-deprecated-apis — components/ui/sheet.tsx:118
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

98. [warning] use-lazy-motion — components/ui/word-reveal.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

99. [warning] use-lazy-motion — components/animate-ui/sliding-number.tsx:3
   Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size

100. [warning] no-react19-deprecated-apis — components/animate-ui/sliding-number.tsx:102
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

101. [warning] no-event-handler — components/animate-ui/sliding-number.tsx:128
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

102. [warning] no-event-handler — components/animate-ui/sliding-number.tsx:125
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

103. [warning] no-event-handler — components/animate-ui/sliding-number.tsx:126
   Avoid using props and effects as an event handler. Instead, move the handler to the parent component.

104. [warning] no-react19-deprecated-apis — components/ui/textarea.tsx:5
   forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly

105. [warning] unused-file — components/animate-ui/sliding-number.tsx:0
   Unused file — not reachable from any entry point

106. [warning] unused-file — components/favorites/index.ts:0
   Unused file — not reachable from any entry point

107. [warning] unused-file — components/shared/theme-provider.tsx:0
   Unused file — not reachable from any entry point

108. [warning] unused-file — components/ui/alert.tsx:0
   Unused file — not reachable from any entry point

109. [warning] unused-file — components/ui/avatar.tsx:0
   Unused file — not reachable from any entry point

110. [warning] unused-file — components/ui/badge.tsx:0
   Unused file — not reachable from any entry point

111. [warning] unused-file — components/ui/flickering-grid.tsx:0
   Unused file — not reachable from any entry point

112. [warning] unused-file — components/ui/gradual-spacing.tsx:0
   Unused file — not reachable from any entry point

113. [warning] unused-file — components/ui/scroll-area.tsx:0
   Unused file — not reachable from any entry point

114. [warning] unused-file — components/ui/sheet.tsx:0
   Unused file — not reachable from any entry point

115. [warning] unused-file — components/ui/skeleton.tsx:0
   Unused file — not reachable from any entry point

116. [warning] unused-export — app/guides-og/[...slug]/og.tsx:31
   Unused export: `generate`

117. [warning] unused-export — app/resources-og/[...slug]/og.tsx:31
   Unused export: `generate`

118. [warning] unused-export — lib/favorites.ts:9
   Unused export: `validateFavoriteResource`

119. [warning] unused-export — lib/favorites.ts:35
   Unused export: `getCategoryDisplayName`

120. [warning] unused-dependency — package.json:0
   Unused dependency: `zod`

121. [warning] unused-dev-dependency — package.json:0
   Unused devDependency: `@trivago/prettier-plugin-sort-imports`

❌ Errors (1)

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

require-reduced-motion

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

File Lines
package.json 0

⚠️ Warnings (120)

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

no-react19-deprecated-apis

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+.

File Lines
components/ui/table.tsx 5, 19, 31, 43, 58, 73, 88, 103
components/ui/card.tsx 5, 20, 32, 44, 56, 68
components/ui/sheet.tsx 19, 57, 106, 118
components/ui/alert.tsx 23, 36, 48
components/ui/avatar.tsx 9, 24, 36
…and 10 more files view on react.review
Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size · 12 in 12 files

use-lazy-motion

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

File Lines
components/shared/home/guides-card.tsx 11
components/animate-ui/text/sliding-number.tsx 3
components/shared/home/hero/hero-image.tsx 3
components/animate-ui/github-stars-button.tsx 4
components/shared/home/section-title.tsx 3
…and 7 more files view on react.review
Unused file — not reachable from any entry point · 11 in 11 files

unused-file

Delete the file if it is truly unreachable, or import it from an entry point.

File Lines
components/animate-ui/sliding-number.tsx 0
components/favorites/index.ts 0
components/shared/theme-provider.tsx 0
components/ui/alert.tsx 0
components/ui/avatar.tsx 0
…and 6 more files view on react.review
Avoid using props and effects as an event handler. Instead, move the handler to the parent component. · 10 in 3 files

no-event-handler

Move the side effect into the event handler that triggers it, instead of guarding on its state inside a useEffect. See https://react.dev/learn/you-might-not-need-an-effect#sharing-logic-between-event-handlers

File Lines
components/animate-ui/github-stars-button.tsx 99, 100, 102, 121
components/animate-ui/text/sliding-number.tsx 131, 132, 134
components/animate-ui/sliding-number.tsx 125, 126, 128
w-16 h-16 → use the shorthand size-16 (Tailwind v3.4+) · 8 in 7 files

design-no-redundant-size-axes

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

File Lines
components/favorites/favorites-page.tsx 52, 105
components/ui/checkbox.tsx 25
components/ui/slider.tsx 24
components/animate-ui/github-stars-button.tsx 255
components/animate-ui/buttons/icon.tsx 108
…and 2 more files view on react.review
Array index "index" used as key — causes bugs when list is reordered or filtered · 5 in 3 files

no-array-index-as-key

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

File Lines
components/shared/mdx-elements.tsx 298, 338, 345
components/ui/gradual-spacing.tsx 30
components/ui/marquee.tsx 38
Declare only one React component per file. Found extra component: AlertTitle. · 4 in 2 files

no-multi-comp

Move secondary components into their own files.

File Lines
components/ui/alert.tsx 36, 48
components/ui/avatar.tsx 24, 36
scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance · 4 in 2 files

no-scale-from-zero

Use initial={{ scale: 0.95, opacity: 0 }} — elements should deflate like a balloon, not vanish into a point

File Lines
components/animate-ui/buttons/icon.tsx 74, 76, 109
components/animate-ui/github-stars-button.tsx 256
Unused export: `generate` · 4 in 3 files

unused-export

Drop the export keyword (or remove the declaration) if no other module uses this symbol.

File Lines
lib/favorites.ts 9, 35
app/guides-og/[...slug]/og.tsx 31
app/resources-og/[...slug]/og.tsx 31
Prefer the semantic `<img>` element over `role="img"` on a generic tag. · 3 in 2 files

prefer-tag-over-role

Replace role with the semantic HTML element when one exists.

File Lines
components/shared/home/resources-marquee.tsx 99, 137
components/shared/resources/custom-card.tsx 46
"handleDisplayParticles" is read only inside `on` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render · 3 in 2 files

prefer-use-effect-event

Wrap the callback with useEffectEvent(callback) (React 19+) and call the resulting binding from inside the sub-handler. The Effect Event captures the latest props/state without being a reactive dep, so the effect doesn't re-subscribe on every parent render. See https://react.dev/reference/react/useEffectEvent

File Lines
components/ui/flickering-grid.tsx 162, 162
components/animate-ui/github-stars-button.tsx 118
Array index in `key` doesn't uniquely identify the element — re-renders may use stale state. · 3 in 1 file

no-array-index-key

Use a stable, data-derived key instead of the array index.

File Lines
components/shared/mdx-elements.tsx 298, 338, 345
Heading elements must contain accessible text content (or `aria-label` / `aria-labelledby`). · 2 in 2 files

heading-has-content

Provide visible or aria-labelled text in every heading.

File Lines
components/ui/alert.tsx 40
components/ui/card.tsx 36
SVG d attribute uses 4+ decimal precision — truncate to 1–2 decimals to shrink markup with no visible difference · 2 in 2 files

rendering-svg-precision

Truncate path/points/transform decimals to 1–2 digits — sub-pixel precision adds bytes with no visible difference

File Lines
app/resources-og/[...slug]/og.tsx 100
app/guides-og/[...slug]/og.tsx 100
Inline render function "renderNumberSegments()" — extract to a separate component for proper reconciliation · 2 in 1 file

no-render-in-render

Extract to a named component: const ListItem = ({ item }) =&gt; &lt;div&gt;{item.name}&lt;/div&gt;

File Lines
components/animate-ui/github-stars-button.tsx 275, 280
Page without metadata or generateMetadata export — hurts SEO · 1 in 1 file

nextjs-missing-metadata

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

File Lines
app/(home)/page.tsx 1
useMemo wrapping a trivially cheap expression — memo overhead exceeds the computation · 1 in 1 file

no-usememo-simple-expression

Remove useMemo — property access, math, and ternaries are already cheap without memoization

File Lines
components/animate-ui/github-stars-button.tsx 73
fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component · 1 in 1 file

no-fetch-in-effect

Use useQuery() from @tanstack/react-query, useSWR(), or fetch in a Server Component instead

File Lines
components/animate-ui/github-stars-button.tsx 78
Non-descriptive handler name "handleClick" — name should describe what it does, not when it runs · 1 in 1 file

no-generic-handler-names

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

File Lines
components/animate-ui/github-stars-button.tsx 182
.filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of · 1 in 1 file

js-combine-iterations

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

File Lines
lib/favorites.ts 27
Context `value` prop is constructed inline — wrap with `useMemo`/`useCallback` or hoist a constant to avoid re-renders. · 1 in 1 file

jsx-no-constructed-context-values

Memoize the context value (useMemo) or hoist it outside the render.

File Lines
components/shared/page-context.tsx 19
space-x-1 on a flex/grid parent — use gap-x-1 instead. Per-sibling margins phantom-gap on conditional render and don't mirror in RTL · 1 in 1 file

design-no-space-on-flex-children

Use gap-* on the flex/grid parent. space-x-* / space-y-* produce phantom gaps when a sibling is conditionally rendered, lose vertical spacing on wrapped lines, and don't mirror in RTL

File Lines
components/ui/gradual-spacing.tsx 26
useState "isInView" is updated but never read in the component's return — use useRef so updates don't trigger re-renders · 1 in 1 file

rerender-state-only-in-handlers

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

File Lines
components/ui/flickering-grid.tsx 27
Avoid adjusting state when a prop changes. Instead, adjust the state directly during render, or refactor your state to avoid this need entirely. · 1 in 1 file

no-adjust-state-on-prop-change

Adjust the state inline during render instead of via a useEffect, or refactor the state to avoid the need entirely. See https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes

File Lines
components/ui/flickering-grid.tsx 149
Unused dependency: `zod` · 1 in 1 file

unused-dependency

Remove the dependency from package.json if it is genuinely unused.

File Lines
package.json 0
Unused devDependency: `@trivago/prettier-plugin-sort-imports` · 1 in 1 file

unused-dev-dependency

Remove the dependency from package.json if it is genuinely unused.

File Lines
package.json 0

Reviewed by reactreview for commit 31a1639. Configure here.

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