Skip to content

React Review Audit #1

Description

@react-doctor
⚠️ 21 warnings 92 score
Copy as prompt
Fix the following React Review diagnostics in my codebase.

## Warnings (21)

1. [warning] no-danger — src/components/Chat/HighlightedCode.tsx:77
   Do not use `dangerouslySetInnerHTML` prop

2. [warning] no-cascading-set-state — src/components/Chat/HighlightedCode.tsx:35
   3 setState calls in a single useEffect — consider using useReducer or deriving state

3. [warning] js-batch-dom-css — src/components/Chat/InputArea.tsx:357
   Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows

4. [warning] js-batch-dom-css — src/components/Chat/MessageBubble.tsx:321
   Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows

5. [warning] js-batch-dom-css — src/components/Chat/MessageBubble.tsx:360
   Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows

6. [warning] async-defer-await — src/hooks/useChat.ts:356
   await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast

7. [warning] async-await-in-loop — src/hooks/useChat.ts:444
   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

8. [warning] async-defer-await — src/hooks/useChat.ts:555
   await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast

9. [warning] async-defer-await — src/hooks/useChat.ts:870
   await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast

10. [warning] no-cascading-set-state — src/hooks/useChat.ts:1059
   9 setState calls in a single useEffect — consider using useReducer or deriving state

11. [warning] no-fetch-in-effect — src/hooks/useChat.ts:1059
   fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component

12. [warning] async-defer-await — src/hooks/useChat.ts:1094
   await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast

13. [warning] no-array-index-as-key — src/components/Chat/ToolCard.tsx:79
   Array index "i" used as key — causes bugs when list is reordered or filtered

14. [warning] no-giant-component — src/components/Settings/SettingsPanel.tsx:214
   Component "SettingsPanel" is 484 lines — consider breaking it into smaller focused components

15. [warning] no-giant-component — src/components/WorkspacePicker.tsx:130
   Component "WorkspacePicker" is 450 lines — consider breaking it into smaller focused components

16. [warning] no-array-index-as-key — src/components/WorkspacePicker.tsx:408
   Array index "i" used as key — causes bugs when list is reordered or filtered

17. [warning] no-render-in-render — src/components/Settings/ProviderCard.tsx:126
   Inline render function "renderNameHint()" — extract to a separate component for proper reconciliation

18. [warning] js-set-map-lookups — src/components/Chat/MarkdownBlock.tsx:129
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

19. [warning] no-giant-component — src/App.tsx:125
   Component "AppContent" is 310 lines — consider breaking it into smaller focused components

20. [warning] prefer-useReducer — src/App.tsx:125
   Component "AppContent" has 7 useState calls — consider useReducer for related state

21. [warning] async-defer-await — src/App.tsx:311
   await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast

⚠️ Warnings (21)

await blocks the function before an early-return that doesn't use the awaited value — move the await after the synchronous guard so the skip path stays fast · 5 in 2 files

async-defer-await

Move the await after the synchronous early-return guard so the skip path stays fast

File Lines
src/hooks/useChat.ts 356, 555, 870, 1094
src/App.tsx 311
Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows · 3 in 2 files

js-batch-dom-css

Batch DOM/CSS reads and writes — interleaving them inside a loop causes layout thrashing. Read first, then write

File Lines
src/components/Chat/MessageBubble.tsx 321, 360
src/components/Chat/InputArea.tsx 357
Component "SettingsPanel" is 484 lines — consider breaking it into smaller focused components · 3 in 3 files

no-giant-component

Extract logical sections into focused components: <UserHeader />, <UserActions />, etc.

File Lines
src/components/Settings/SettingsPanel.tsx 214
src/components/WorkspacePicker.tsx 130
src/App.tsx 125
3 setState calls in a single useEffect — consider using useReducer or deriving state · 2 in 2 files

no-cascading-set-state

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

File Lines
src/components/Chat/HighlightedCode.tsx 35
src/hooks/useChat.ts 1059
Array index "i" used as key — causes bugs when list is reordered or filtered · 2 in 2 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
src/components/Chat/ToolCard.tsx 79
src/components/WorkspacePicker.tsx 408
Do not use `dangerouslySetInnerHTML` prop · 1 in 1 file

no-danger

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

File Lines
src/components/Chat/HighlightedCode.tsx 77
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 · 1 in 1 file

async-await-in-loop

Collect the items and use await Promise.all(items.map(...)) to run independent operations concurrently

File Lines
src/hooks/useChat.ts 444
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
src/hooks/useChat.ts 1059
Inline render function "renderNameHint()" — extract to a separate component for proper reconciliation · 1 in 1 file

no-render-in-render

Extract to a named component: const ListItem = ({ item }) => <div>{item.name}</div>

File Lines
src/components/Settings/ProviderCard.tsx 126
array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups · 1 in 1 file

js-set-map-lookups

Use a Set or Map for repeated membership tests / keyed lookups — Array.includes/find is O(n) per call

File Lines
src/components/Chat/MarkdownBlock.tsx 129
Component "AppContent" has 7 useState calls — consider useReducer for related state · 1 in 1 file

prefer-useReducer

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

File Lines
src/App.tsx 125

Reviewed by reactreview for commit b7b4c46. Configure here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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