React Review Audit
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 30/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- nextjs, react, typescript
- Área
- frontend
Línea de trabajo
Comienza con los cuatro diagnósticos de rules-of-hooks en apps/web/app/threads/[id]/_components/RightSidebar.tsx y luego revisa las rutas restantes señaladas, como thread-detail-client.tsx, devices-client.tsx, code-view.tsx y sidebar.tsx. Usa los diagnósticos enumerados como lista de comprobación de la auditoría; se considera terminado cuando los errores y advertencias señalados se hayan resuelto en los archivos mencionados.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Score: 76/100 · 4 errors · 74 warnings
Copy as prompt
Fix the following React Review diagnostics in my codebase.
## Errors (4)
1. [error] rules-of-hooks — apps/web/app/threads/[id]/_components/RightSidebar.tsx:182
React Hook "useRef" is called conditionally. React Hooks must be called in the exact same order in every component render.
2. [error] rules-of-hooks — apps/web/app/threads/[id]/_components/RightSidebar.tsx:183
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
3. [error] rules-of-hooks — apps/web/app/threads/[id]/_components/RightSidebar.tsx:184
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
4. [error] rules-of-hooks — apps/web/app/threads/[id]/_components/RightSidebar.tsx:186
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
## Warnings (74)
5. [warning] no-react19-deprecated-apis — apps/web/src/components/ui/animated-beam-logos.tsx:3
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
6. [warning] nextjs-missing-metadata — apps/web/app/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
7. [warning] prefer-useReducer — apps/web/app/threads/[id]/thread-detail-client.tsx:39
Component "ThreadDetailClient" has 7 useState calls — consider useReducer for related state
8. [warning] no-giant-component — apps/web/app/threads/[id]/thread-detail-client.tsx:39
Component "ThreadDetailClient" is 345 lines — consider breaking it into smaller focused components
9. [warning] react-compiler-destructure-method — apps/web/app/threads/[id]/thread-detail-client.tsx:233
Destructure for clarity: `const { back } = useRouter()` then call `back(...)` directly — easier for React Compiler to memoize and clearer about which methods this component depends on
10. [warning] react-compiler-destructure-method — apps/web/app/threads/[id]/thread-detail-client.tsx:284
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
11. [warning] nextjs-missing-metadata — apps/web/app/devices/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
12. [warning] nextjs-missing-metadata — apps/web/app/threads/[id]/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
13. [warning] no-autofocus — apps/web/app/devices/devices-client.tsx:142
The `autoFocus` attribute is found here, which can cause usability issues for sighted and non-sighted users.
14. [warning] rendering-hydration-mismatch-time — apps/web/app/devices/devices-client.tsx:47
Date.now() reachable from JSX renders differently on server vs client — wrap in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional
15. [warning] rendering-hydration-mismatch-time — apps/web/app/devices/devices-client.tsx:47
Date.now() reachable from JSX renders differently on server vs client — wrap in useEffect+useState (client-only) or add suppressHydrationWarning to the parent if intentional
16. [warning] no-danger — apps/web/src/components/ai-elements/code-view.tsx:183
Do not use `dangerouslySetInnerHTML` prop
17. [warning] js-set-map-lookups — apps/web/src/components/ai-elements/code-view.tsx:295
array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups
18. [warning] js-combine-iterations — apps/web/src/components/ai-elements/code-view.tsx:307
.map().filter() iterates the array twice — combine into a single loop with .reduce() or for...of
19. [warning] no-long-transition-duration — apps/web/app/threads/[id]/_components/TodoPanel.tsx:151
1500ms transition is too slow for UI feedback — keep transitions under 1000ms. Use longer durations only for page-load hero animations
20. [warning] no-react19-deprecated-apis — apps/web/src/components/right-sidebar-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'`
21. [warning] prefer-use-effect-event — apps/web/app/threads/[id]/_components/RightSidebar.tsx:101
"onClose" is read only inside `addEventListener` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render
22. [warning] no-derived-useState — apps/web/app/threads/[id]/_components/RightSidebar.tsx:89
useState initialized from prop "defaultTab" — if this value should stay in sync with the prop, derive it during render instead
23. [warning] no-effect-event-handler — apps/web/app/threads/[id]/_components/RightSidebar.tsx:91
useEffect simulating an event handler — move logic to an actual event handler instead
24. [warning] no-cascading-set-state — apps/web/app/threads/[id]/_components/RightSidebar.tsx:264
4 setState calls in a single useEffect — consider using useReducer or deriving state
25. [warning] design-no-three-period-ellipsis — apps/web/app/threads/[id]/_components/RightSidebar.tsx:403
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
26. [warning] rendering-hydration-mismatch-time — apps/web/src/components/landing-page.tsx:94
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
27. [warning] prefer-useReducer — apps/web/app/workspaces/workspaces-client.tsx:137
Component "NewWorkspaceModal" has 5 useState calls — consider useReducer for related state
28. [warning] no-derived-useState — apps/web/app/workspaces/workspaces-client.tsx:235
useState initialized from prop "workspace" — if this value should stay in sync with the prop, derive it during render instead
29. [warning] no-derived-useState — apps/web/app/workspaces/workspaces-client.tsx:236
useState initialized from prop "workspace" — if this value should stay in sync with the prop, derive it during render instead
30. [warning] no-react19-deprecated-apis — apps/web/src/components/icons.tsx:90
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
31. [warning] async-await-in-loop — apps/web/app/api/daemon/pair/poll/route.ts:15
await inside a while-loop runs the calls sequentially — for independent operations, collect them and use `await Promise.all(items.map(...))` to run them concurrently
32. [warning] nextjs-missing-metadata — apps/web/app/workspaces/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
33. [warning] no-array-index-as-key — apps/web/app/threads/[id]/_components/MessageBubble.tsx:110
Array index "i" used as key — causes bugs when list is reordered or filtered
34. [warning] no-array-index-as-key — apps/web/app/threads/[id]/_components/MessageBubble.tsx:117
Array index "i" used as key — causes bugs when list is reordered or filtered
35. [warning] js-flatmap-filter — apps/web/app/threads/[id]/_components/MessageBubble.tsx:172
.map().filter(Boolean) iterates twice — use .flatMap() to transform and filter in a single pass
36. [warning] rendering-hydration-mismatch-time — apps/web/app/threads/threads-client.tsx:50
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
37. [warning] rendering-hydration-mismatch-time — apps/web/app/threads/threads-client.tsx:50
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
38. [warning] rendering-hydration-mismatch-time — apps/web/app/threads/threads-client.tsx:50
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
39. [warning] js-batch-dom-css — apps/web/app/threads/[id]/_components/Composer.tsx:65
Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows
40. [warning] no-prevent-default — apps/web/app/threads/[id]/_components/Composer.tsx:158
preventDefault() on <form> onSubmit — form won't work without JavaScript. Consider using a server action for progressive enhancement
41. [warning] react-compiler-destructure-method — apps/web/src/components/auth-layout.tsx:56
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
42. [warning] no-generic-handler-names — apps/web/src/components/auth-layout.tsx:65
Non-descriptive handler name "handleClick" — name should describe what it does, not when it runs
43. [warning] nextjs-missing-metadata — apps/web/app/threads/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
44. [warning] nextjs-missing-metadata — apps/web/app/sign-up/[[...sign-up]]/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
45. [warning] label-has-associated-control — apps/web/src/components/app-shell/sidebar.tsx:400
A form label must be associated with a control.
46. [warning] label-has-associated-control — apps/web/src/components/app-shell/sidebar.tsx:494
A form label must be associated with a control.
47. [warning] label-has-associated-control — apps/web/src/components/app-shell/sidebar.tsx:510
A form label must be associated with a control.
48. [warning] label-has-associated-control — apps/web/src/components/app-shell/sidebar.tsx:521
A form label must be associated with a control.
49. [warning] prefer-useReducer — apps/web/src/components/app-shell/sidebar.tsx:43
Component "AppSidebar" has 5 useState calls — consider useReducer for related state
50. [warning] rerender-state-only-in-handlers — apps/web/src/components/app-shell/sidebar.tsx:51
useState "searchOpen" is updated but never read in the component's return — use useRef so updates don't trigger re-renders
51. [warning] js-combine-iterations — apps/web/src/components/app-shell/sidebar.tsx:77
.filter().map() iterates the array twice — combine into a single loop with .reduce() or for...of
52. [warning] no-effect-chain — apps/web/src/components/app-shell/sidebar.tsx:366
useEffect reacts to "wsId" which is set by another useEffect — chains of effects add an extra render per link and become rigid as code evolves. Compute what you can during render and write all related state inside the event handler that originally fires the chain
53. [warning] react-compiler-destructure-method — apps/web/src/components/app-shell/sidebar.tsx:385
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
54. [warning] no-cascading-set-state — apps/web/src/components/app-shell/sidebar.tsx:463
3 setState calls in a single useEffect — consider using useReducer or deriving state
55. [warning] no-effect-event-handler — apps/web/src/components/app-shell/sidebar.tsx:463
useEffect simulating an event handler — move logic to an actual event handler instead
56. [warning] design-no-em-dash-in-jsx-text — apps/web/src/components/ai-elements/tool-call.tsx:129
Em dash (—) in JSX text reads as model output — replace with comma, colon, semicolon, or parentheses
57. [warning] nextjs-missing-metadata — apps/web/app/sign-in/[[...sign-in]]/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
58. [warning] no-redundant-roles — apps/web/src/components/ai-elements/timeline.tsx:387
The `ol` element has an implicit role of `list`. Defining this explicitly is redundant and should be avoided.
59. [warning] use-lazy-motion — apps/web/src/components/ai-elements/timeline.tsx:3
Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size
60. [warning] js-set-map-lookups — apps/web/src/components/ai-elements/timeline.tsx:461
array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups
61. [warning] design-no-em-dash-in-jsx-text — apps/web/src/components/ai-elements/timeline.tsx:763
Em dash (—) in JSX text reads as model output — replace with comma, colon, semicolon, or parentheses
62. [warning] prefer-use-effect-event — apps/web/src/components/ai-elements/response.tsx:48
"onClose" is read only inside `addEventListener` — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render
63. [warning] no-effect-event-handler — apps/web/src/components/ai-elements/response.tsx:50
useEffect simulating an event handler — move logic to an actual event handler instead
64. [warning] no-danger — apps/web/src/components/ai-elements/grep-code-view.tsx:75
Do not use `dangerouslySetInnerHTML` prop
65. [warning] no-react19-deprecated-apis — apps/web/src/components/ui/matrix.tsx:422
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
66. [warning] async-await-in-loop — apps/web/app/api/daemon/runs/pending/route.ts:19
await inside a while-loop runs the calls sequentially — for independent operations, collect them and use `await Promise.all(items.map(...))` to run them concurrently
67. [warning] no-react19-deprecated-apis — apps/web/src/components/ui/terminal.tsx:6
useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`
68. [warning] use-lazy-motion — apps/web/src/components/ui/terminal.tsx:14
Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size
69. [warning] rerender-state-only-in-handlers — apps/web/src/components/ui/terminal.tsx:140
useState "started" is updated but never read in the component's return — use useRef so updates don't trigger re-renders
70. [warning] no-cascading-set-state — apps/web/src/components/ui/terminal.tsx:162
3 setState calls in a single useEffect — consider using useReducer or deriving state
71. [warning] no-array-index-as-key — apps/web/src/components/ui/terminal.tsx:266
Array index "index" used as key — causes bugs when list is reordered or filtered
72. [warning] design-no-redundant-size-axes — apps/web/src/components/ui/terminal.tsx:282
w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)
73. [warning] design-no-redundant-size-axes — apps/web/src/components/ui/terminal.tsx:283
w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)
74. [warning] design-no-redundant-size-axes — apps/web/src/components/ui/terminal.tsx:284
w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)
75. [warning] no-react19-deprecated-apis — apps/web/src/components/ui/sidebar.tsx:48
useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`
76. [warning] no-derived-useState — apps/web/src/components/ui/sidebar.tsx:74
useState initialized from prop "defaultOpen" — if this value should stay in sync with the prop, derive it during render instead
77. [warning] no-inline-exhaustive-style — apps/web/src/lib/dotmatrix-core.tsx:784
8 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
78. [warning] use-lazy-motion — apps/web/src/components/ui/animated-beam.tsx:3
Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size
❌ Errors (4)
rules-of-hooks
React Hook "useRef" is called conditionally. React Hooks must be called in the exact same order in every component render.
Move the Hook call before the condition, or call it unconditionally and branch inside the Hook/effect instead.
apps/web/app/threads/[id]/_components/RightSidebar.tsx:182
apps/web/app/threads/[id]/_components/RightSidebar.tsx:183
apps/web/app/threads/[id]/_components/RightSidebar.tsx:184
apps/web/app/threads/[id]/_components/RightSidebar.tsx:186
⚠️ Warnings (74)
nextjs-missing-metadata
Page without metadata or generateMetadata export — hurts SEO
Add
export const metadata = { title: '...', description: '...' }orexport async function generateMetadata()
apps/web/app/page.tsx:1
apps/web/app/devices/page.tsx:1
apps/web/app/threads/[id]/page.tsx:1
apps/web/app/workspaces/page.tsx:1
apps/web/app/threads/page.tsx:1
apps/web/app/sign-up/[[...sign-up]]/page.tsx:1
apps/web/app/sign-in/[[...sign-in]]/page.tsx:1
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
refas a regular prop on function components —forwardRefis no longer needed in React 19+. ReplaceuseContext(X)withuse(X)for branch-aware context reads. Only enabled on projects detected as React 19+.
apps/web/src/components/ui/animated-beam-logos.tsx:3
apps/web/src/components/right-sidebar-context.tsx:3
apps/web/src/components/icons.tsx:90
apps/web/src/components/ui/matrix.tsx:422
apps/web/src/components/ui/terminal.tsx:6
apps/web/src/components/ui/sidebar.tsx:48
rendering-hydration-mismatch-time
Date.now() 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
apps/web/app/devices/devices-client.tsx:47
apps/web/app/devices/devices-client.tsx:47
apps/web/src/components/landing-page.tsx:94
apps/web/app/threads/threads-client.tsx:50
apps/web/app/threads/threads-client.tsx:50
apps/web/app/threads/threads-client.tsx:50
react-compiler-destructure-method
Destructure for clarity: const { back } = useRouter() then call back(...) 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 callpush(...)directly — clearer dependency graph and easier for React Compiler to memoize
apps/web/app/threads/[id]/thread-detail-client.tsx:233
apps/web/app/threads/[id]/thread-detail-client.tsx:284
apps/web/src/components/auth-layout.tsx:56
apps/web/src/components/app-shell/sidebar.tsx:385
no-derived-useState
useState initialized from prop "defaultTab" — 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)
apps/web/app/threads/[id]/_components/RightSidebar.tsx:89
apps/web/app/workspaces/workspaces-client.tsx:235
apps/web/app/workspaces/workspaces-client.tsx:236
apps/web/src/components/ui/sidebar.tsx:74
label-has-associated-control
A form label must be associated with a control.
Either give the label a
htmlForattribute with the id of the associated control, or wrap the label around the control.
apps/web/src/components/app-shell/sidebar.tsx:400
apps/web/src/components/app-shell/sidebar.tsx:494
apps/web/src/components/app-shell/sidebar.tsx:510
apps/web/src/components/app-shell/sidebar.tsx:521
prefer-useReducer
Component "ThreadDetailClient" has 7 useState calls — consider useReducer for related state
Group related state:
const [state, dispatch] = useReducer(reducer, { field1, field2, ... })
apps/web/app/threads/[id]/thread-detail-client.tsx:39
apps/web/app/workspaces/workspaces-client.tsx:137
apps/web/src/components/app-shell/sidebar.tsx:43
no-effect-event-handler
useEffect simulating an event handler — move logic to an actual event handler instead
Move the conditional logic into onClick, onChange, or onSubmit handlers directly
apps/web/app/threads/[id]/_components/RightSidebar.tsx:91
apps/web/src/components/app-shell/sidebar.tsx:463
apps/web/src/components/ai-elements/response.tsx:50
no-cascading-set-state
4 setState calls in a single useEffect — consider using useReducer or deriving state
Combine into useReducer:
const [state, dispatch] = useReducer(reducer, initialState)
apps/web/app/threads/[id]/_components/RightSidebar.tsx:264
apps/web/src/components/app-shell/sidebar.tsx:463
apps/web/src/components/ui/terminal.tsx:162
no-array-index-as-key
Array index "i" used as key — causes bugs when list is reordered or filtered
Use a stable unique identifier:
key={item.id}orkey={item.slug}— index keys break on reorder/filter
apps/web/app/threads/[id]/_components/MessageBubble.tsx:110
apps/web/app/threads/[id]/_components/MessageBubble.tsx:117
apps/web/src/components/ui/terminal.tsx:266
use-lazy-motion
Import "m" with LazyMotion instead of "motion" — saves ~30kb in bundle size
Use
import { LazyMotion, m } from "framer-motion"withdomAnimationfeatures — saves ~30kb
apps/web/src/components/ai-elements/timeline.tsx:3
apps/web/src/components/ui/terminal.tsx:14
apps/web/src/components/ui/animated-beam.tsx:3
design-no-redundant-size-axes
w-2 h-2 → use the shorthand size-2 (Tailwind v3.4+)
Collapse
w-N h-Ntosize-N(Tailwind v3.4+) when both axes match
apps/web/src/components/ui/terminal.tsx:282
apps/web/src/components/ui/terminal.tsx:283
apps/web/src/components/ui/terminal.tsx:284
no-danger
Do not use dangerouslySetInnerHTML prop
dangerouslySetInnerHTMLis a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities.
apps/web/src/components/ai-elements/code-view.tsx:183
apps/web/src/components/ai-elements/grep-code-view.tsx:75
js-set-map-lookups
array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups
Use a
SetorMapfor repeated membership tests / keyed lookups —Array.includes/findis O(n) per call
apps/web/src/components/ai-elements/code-view.tsx:295
apps/web/src/components/ai-elements/timeline.tsx:461
js-combine-iterations
.map().filter() 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 afor...ofloop to avoid iterating the array twice
apps/web/src/components/ai-elements/code-view.tsx:307
apps/web/src/components/app-shell/sidebar.tsx:77
prefer-use-effect-event
"onClose" is read only inside addEventListener — wrap it with useEffectEvent and remove it from the dep array so the effect doesn't re-synchronize on every parent render
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
apps/web/app/threads/[id]/_components/RightSidebar.tsx:101
apps/web/src/components/ai-elements/response.tsx:48
async-await-in-loop
await inside a while-loop runs the calls sequentially — for independent operations, collect them and use await Promise.all(items.map(...)) to run them concurrently
Collect the items and use
await Promise.all(items.map(...))to run independent operations concurrently
apps/web/app/api/daemon/pair/poll/route.ts:15
apps/web/app/api/daemon/runs/pending/route.ts:19
rerender-state-only-in-handlers
useState "searchOpen" 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
apps/web/src/components/app-shell/sidebar.tsx:51
apps/web/src/components/ui/terminal.tsx:140
design-no-em-dash-in-jsx-text
Em dash (—) in JSX text reads as model output — replace with comma, colon, semicolon, or parentheses
Replace em dashes in JSX text with commas, colons, semicolons, periods, or parentheses — em dashes read as model-output filler
apps/web/src/components/ai-elements/tool-call.tsx:129
apps/web/src/components/ai-elements/timeline.tsx:763
no-giant-component
Component "ThreadDetailClient" is 345 lines — consider breaking it into smaller focused components
Extract logical sections into focused components:
<UserHeader />,<UserActions />, etc.
apps/web/app/threads/[id]/thread-detail-client.tsx:39
no-autofocus
The autoFocus attribute is found here, which can cause usability issues for sighted and non-sighted users.
Remove the
autoFocusattribute.
apps/web/app/devices/devices-client.tsx:142
no-long-transition-duration
1500ms transition is too slow for UI feedback — keep transitions under 1000ms. Use longer durations only for page-load hero animations
Keep UI transitions under 1s — 100-150ms for instant feedback, 200-300ms for state changes, 300-500ms for layout changes. Use longer durations only for page-load hero animations
apps/web/app/threads/[id]/_components/TodoPanel.tsx:151
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…")
apps/web/app/threads/[id]/_components/RightSidebar.tsx:403
js-flatmap-filter
.map().filter(Boolean) iterates twice — use .flatMap() to transform and filter in a single pass
Use
.flatMap(item => condition ? [value] : [])— transforms and filters in a single pass instead of creating an intermediate array
apps/web/app/threads/[id]/_components/MessageBubble.tsx:172
js-batch-dom-css
Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows
Batch DOM/CSS reads and writes — interleaving them inside a loop causes layout thrashing. Read first, then write
apps/web/app/threads/[id]/_components/Composer.tsx:65
no-prevent-default
preventDefault() on <form> onSubmit — form won't work without JavaScript. Consider using a server action for progressive enhancement
Use
<form action={serverAction}>(works without JS) or<button>instead of<a>with preventDefault
apps/web/app/threads/[id]/_components/Composer.tsx:158
no-generic-handler-names
Non-descriptive handler name "handleClick" — name should describe what it does, not when it runs
Rename to describe the action: e.g.
handleSubmit→saveUserProfile,handleClick→toggleSidebar
apps/web/src/components/auth-layout.tsx:65
no-effect-chain
useEffect reacts to "wsId" which is set by another useEffect — chains of effects add an extra render per link and become rigid as code evolves. Compute what you can during render and write all related state inside the event handler that originally fires the chain
Compute as much as possible during render (e.g.
const isGameOver = round > 5) and write all related state inside the event handler that originally fires the chain. Each effect link adds an extra render and makes the code rigid as requirements evolve
apps/web/src/components/app-shell/sidebar.tsx:366
no-redundant-roles
The ol element has an implicit role of list. Defining this explicitly is redundant and should be avoided.
Remove the redundant role
listfrom the elementol.
apps/web/src/components/ai-elements/timeline.tsx:387
no-inline-exhaustive-style
8 inline style properties — extract to a CSS class, CSS module, or styled component for maintainability and reuse
Move styles to a CSS class, CSS module, Tailwind utilities, or a styled component — inline objects with many properties hurt readability and create new references every render
apps/web/src/lib/dotmatrix-core.tsx:784
Last scored May 14, 2026 at 9:39 AM UTC. Maintained by React Review.
- Lenguaje dominante
- TypeScript
- Estrellas
- 0
- Forks
- 0
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
bug v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
modelcontextprotocol/inspector#2458 · 1 comentario ·
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 75/100
railmapgen/rmp-gallery#4068 ·
-
Mend: dependency security vulnerability status: needs triage 🕵️♀️
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
carbon-design-system/ibm-products#9907 ·