Skip to content

React Review Audit #2

@reactreview

Description

@reactreview

Score: 90/100 · 0 errors · 41 warnings

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

## Warnings (41)

1. [warning] prefer-useReducer — src/components/ScriptRunner.tsx:34
   Component "ScriptRunner" has 8 useState calls — consider useReducer for related state

2. [warning] rerender-functional-setstate — src/components/ScriptRunner.tsx:82
   setScriptArgs([...scriptArgs, ...]) — use functional update `setScriptArgs(prev => [...prev, ...])` to avoid stale closures

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

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

5. [warning] click-events-have-key-events — src/components/Sidebar.tsx:142
   Enforce a clickable non-interactive element has at least one keyboard event listener.

6. [warning] click-events-have-key-events — src/components/Sidebar.tsx:156
   Enforce a clickable non-interactive element has at least one keyboard event listener.

7. [warning] no-static-element-interactions — src/components/Sidebar.tsx:142
   Static HTML elements with event handlers require a role.

8. [warning] no-static-element-interactions — src/components/Sidebar.tsx:156
   Static HTML elements with event handlers require a role.

9. [warning] label-has-associated-control — src/components/TriggerForm.tsx:91
   A form label must be associated with a control.

10. [warning] label-has-associated-control — src/components/TriggerForm.tsx:101
   A form label must be associated with a control.

11. [warning] label-has-associated-control — src/components/TriggerForm.tsx:137
   A form label must be associated with a control.

12. [warning] label-has-associated-control — src/components/TriggerForm.tsx:148
   A form label must have accessible text.

13. [warning] prefer-useReducer — src/components/TriggerForm.tsx:15
   Component "TriggerForm" has 7 useState calls — consider useReducer for related state

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

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

16. [warning] prefer-useReducer — src/components/SettingsView.tsx:10
   Component "SettingsView" has 8 useState calls — consider useReducer for related state

17. [warning] no-giant-component — src/components/SettingsView.tsx:10
   Component "SettingsView" is 310 lines — consider breaking it into smaller focused components

18. [warning] no-cascading-set-state — src/components/SettingsView.tsx:61
   4 setState calls in a single useEffect — consider using useReducer or deriving state

19. [warning] click-events-have-key-events — src/components/PackagesView.tsx:107
   Enforce a clickable non-interactive element has at least one keyboard event listener.

20. [warning] click-events-have-key-events — src/components/PackagesView.tsx:126
   Enforce a clickable non-interactive element has at least one keyboard event listener.

21. [warning] no-static-element-interactions — src/components/PackagesView.tsx:107
   Static HTML elements with event handlers require a role.

22. [warning] no-static-element-interactions — src/components/PackagesView.tsx:126
   Static HTML elements with event handlers require a role.

23. [warning] prefer-useReducer — src/components/PackagesView.tsx:10
   Component "PackagesView" has 5 useState calls — consider useReducer for related state

24. [warning] rerender-state-only-in-handlers — src/components/PackagesView.tsx:13
   useState "loading" is updated but never read in the component's return — use useRef so updates don't trigger re-renders

25. [warning] design-no-three-period-ellipsis — src/components/PackagesView.tsx:73
   Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)

26. [warning] rerender-state-only-in-handlers — src/components/PackagesView.tsx:154
   useState "loading" is updated but never read in the component's return — use useRef so updates don't trigger re-renders

27. [warning] design-no-three-period-ellipsis — src/components/PackagesView.tsx:189
   Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)

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

29. [warning] js-tosorted-immutable — src/utils/fuzzy.ts:41
   [...array].sort() — use array.toSorted() for immutable sorting (ES2023)

30. [warning] js-set-map-lookups — src/utils/fuzzy.ts:52
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

31. [warning] label-has-associated-control — src/components/GlobalVarForm.tsx:50
   A form label must be associated with a control.

32. [warning] label-has-associated-control — src/components/GlobalVarForm.tsx:60
   A form label must be associated with a control.

33. [warning] no-danger — src/components/CodeEditor.tsx:296
   Do not use `dangerouslySetInnerHTML` prop

34. [warning] js-set-map-lookups — src/components/CodeEditor.tsx:93
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

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

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

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

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

39. [warning] js-flatmap-filter — src/index.tsx:98
   .map().filter(Boolean) iterates twice — use .flatMap() to transform and filter in a single pass

40. [warning] rerender-functional-setstate — src/index.tsx:117
   setTriggers([...triggers, ...]) — use functional update `setTriggers(prev => [...prev, ...])` to avoid stale closures

41. [warning] rerender-functional-setstate — src/index.tsx:332
   setGlobalVars([...globalVars, ...]) — use functional update `setGlobalVars(prev => [...prev, ...])` to avoid stale closures

⚠️ Warnings (41)

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} or key={item.slug} — index keys break on reorder/filter

src/components/ScriptRunner.tsx:144
src/components/ScriptRunner.tsx:211
src/components/ScriptLangView.tsx:179
src/components/ScriptLangView.tsx:300
src/components/PackagesView.tsx:227
src/components/CodeEditor.tsx:287

label-has-associated-control

A form label must be associated with a control.

Either give the label a htmlFor attribute with the id of the associated control, or wrap the label around the control.

src/components/TriggerForm.tsx:91
src/components/TriggerForm.tsx:101
src/components/TriggerForm.tsx:137
src/components/TriggerForm.tsx:148
src/components/GlobalVarForm.tsx:50
src/components/GlobalVarForm.tsx:60

js-set-map-lookups

array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

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

src/utils/fuzzy.ts:52
src/components/CodeEditor.tsx:93
src/components/CodeEditor.tsx:140
src/components/CodeEditor.tsx:156
src/components/CodeEditor.tsx:162

prefer-useReducer

Component "ScriptRunner" has 8 useState calls — consider useReducer for related state

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

src/components/ScriptRunner.tsx:34
src/components/TriggerForm.tsx:15
src/components/SettingsView.tsx:10
src/components/PackagesView.tsx:10

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.

src/components/Sidebar.tsx:142
src/components/Sidebar.tsx:156
src/components/PackagesView.tsx:107
src/components/PackagesView.tsx:126

no-static-element-interactions

Static HTML elements with event handlers require a role.

Add a role attribute to this element, or use a semantic HTML element instead.

src/components/Sidebar.tsx:142
src/components/Sidebar.tsx:156
src/components/PackagesView.tsx:107
src/components/PackagesView.tsx:126

rerender-functional-setstate

setScriptArgs([...scriptArgs, ...]) — use functional update setScriptArgs(prev => [...prev, ...]) to avoid stale closures

Use the callback form: setState(prev => prev + 1) to always read the latest value

src/components/ScriptRunner.tsx:82
src/index.tsx:117
src/index.tsx:332

rerender-state-only-in-handlers

useState "loading" 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

src/components/PackagesView.tsx:13
src/components/PackagesView.tsx:154

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…")

src/components/PackagesView.tsx:73
src/components/PackagesView.tsx:189

no-giant-component

Component "SettingsView" is 310 lines — consider breaking it into smaller focused components

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

src/components/SettingsView.tsx:10

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)

src/components/SettingsView.tsx:61

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

src/utils/fuzzy.ts:41

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.

src/components/CodeEditor.tsx:296

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

src/index.tsx:98


Last scored May 13, 2026 at 7:09 PM UTC. Maintained by React Review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions