Skip to content

React Review Audit #1

@reactreview

Description

@reactreview
1 error, ⚠️ 46 warnings 91 score
Copy as prompt
Fix the following React Review diagnostics in my codebase.

## Errors (1)

1. [error] no-nested-component-definition — apps/website/public/budge.iife.js:16363
   Component "C" defined inside "Pu" — creates new instance every render, destroying state

## Warnings (46)

2. [warning] no-giant-component — apps/website/app/terms/page.tsx:8
   Component "TermsPage" is 350 lines — consider breaking it into smaller focused components

3. [warning] no-giant-component — apps/website/components/budge-me-paper-preview.tsx:489
   Component "BudgeMePaperPreview" is 961 lines — consider breaking it into smaller focused components

4. [warning] prefer-useReducer — apps/website/components/budge-me-paper-preview.tsx:492
   Component "BudgeMePaperPreview" has 18 useState calls — consider useReducer for related state

5. [warning] no-cascading-set-state — apps/website/components/budge-me-paper-preview.tsx:547
   6 setState calls in a single useEffect — consider using useReducer or deriving state

6. [warning] no-cascading-set-state — apps/website/components/budge-me-paper-preview.tsx:751
   25 setState calls in a single useEffect — consider using useReducer or deriving state

7. [warning] no-cascading-set-state — apps/website/components/budge-me-paper-preview.tsx:856
   19 setState calls in a single useEffect — consider using useReducer or deriving state

8. [warning] async-await-in-loop — apps/website/components/budge-me-paper-preview.tsx:895
   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

9. [warning] async-await-in-loop — apps/website/components/budge-me-paper-preview.tsx:895
   await inside a for-loop runs the calls sequentially — for independent operations, collect them and use `await Promise.all(items.map(...))` to run them concurrently

10. [warning] async-await-in-loop — apps/website/components/budge-me-paper-preview.tsx:916
   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

11. [warning] async-await-in-loop — apps/website/components/budge-me-paper-preview.tsx:933
   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

12. [warning] no-giant-component — apps/website/app/__budge.tsx:373
   Component "BudgeRuntime" is 352 lines — consider breaking it into smaller focused components

13. [warning] no-cascading-set-state — apps/website/app/__budge.tsx:445
   3 setState calls in a single useEffect — consider using useReducer or deriving state

14. [warning] no-cascading-set-state — apps/website/app/__budge.tsx:480
   6 setState calls in a single useEffect — consider using useReducer or deriving state

15. [warning] no-cascading-set-state — apps/website/app/__budge.tsx:493
   3 setState calls in a single useEffect — consider using useReducer or deriving state

16. [warning] no-cascading-set-state — apps/website/app/__budge.tsx:551
   15 setState calls in a single useEffect — consider using useReducer or deriving state

17. [warning] no-giant-component — apps/website/components/replay/replay-viewer.tsx:375
   Component "ReplayViewer" is 1015 lines — consider breaking it into smaller focused components

18. [warning] no-cascading-set-state — apps/website/components/budge-logo.tsx:81
   8 setState calls in a single useEffect — consider using useReducer or deriving state

19. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:1361
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

20. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:1362
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

21. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:1375
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

22. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:2045
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

23. [warning] js-cache-property-access — apps/website/public/budge.iife.js:4099
   t.memoizedProps.revealOrder is read 4 times inside this loop — hoist into a const at the top of the loop body

24. [warning] no-giant-component — apps/website/public/budge.iife.js:6373
   Component "Hc" is 326 lines — consider breaking it into smaller focused components

25. [warning] js-cache-property-access — apps/website/public/budge.iife.js:10318
   n.style.display is read 3 times inside this loop — hoist into a const at the top of the loop body

26. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:12149
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

27. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:12402
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

28. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:12403
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

29. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:12413
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

30. [warning] js-combine-iterations — apps/website/public/budge.iife.js:12575
   .map().filter() iterates the array twice — combine into a single loop with .reduce() or for...of

31. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:12967
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

32. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:14050
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

33. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:14338
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

34. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:14347
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

35. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:15067
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

36. [warning] no-giant-component — apps/website/public/budge.iife.js:18209
   Component "Bp" is 729 lines — consider breaking it into smaller focused components

37. [warning] no-many-boolean-props — apps/website/public/budge.iife.js:18998
   Component "Up" takes 4 boolean-like props (isProjecting, isProjectionDirty, isSharedProjectionDirty…) — consider compound components or explicit variants instead of stacking flags

38. [warning] rerender-memo-with-default-value — apps/website/public/budge.iife.js:19326
   Default prop value {} creates a new object reference every render — extract to a module-level constant

39. [warning] js-hoist-intl — apps/website/public/budge.iife.js:20039
   new Intl.Segmenter() inside a function — hoist to module scope or wrap in useMemo so it isn't recreated each call

40. [warning] js-set-map-lookups — apps/website/public/budge.iife.js:21437
   array.indexOf() in a loop is O(n) per call — convert to a Set for O(1) lookups

41. [warning] no-giant-component — apps/website/public/budge.iife.js:21644
   Component "Z_" is 599 lines — consider breaking it into smaller focused components

42. [warning] js-tosorted-immutable — packages/budge/src/widget.tsx:372
   [...array].sort() — use array.toSorted() for immutable sorting (ES2023)

43. [warning] js-set-map-lookups — packages/budge/src/widget.tsx:379
   array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

44. [warning] no-giant-component — packages/budge/src/widget.tsx:652
   Component "Budge" is 762 lines — consider breaking it into smaller focused components

45. [warning] prefer-useReducer — packages/budge/src/widget.tsx:655
   Component "Budge" has 12 useState calls — consider useReducer for related state

46. [warning] no-cascading-set-state — packages/budge/src/widget.tsx:744
   7 setState calls in a single useEffect — consider using useReducer or deriving state

47. [warning] no-cascading-set-state — packages/budge/src/widget.tsx:1082
   21 setState calls in a single useEffect — consider using useReducer or deriving state

❌ Errors (1)

Component "C" defined inside "Pu" — creates new instance every render, destroying state · 1 in 1 file

no-nested-component-definition

Move to a separate file or to module scope above the parent component

File Lines
apps/website/public/budge.iife.js 16363

⚠️ Warnings (46)

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

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
apps/website/public/budge.iife.js 1361, 1362, 1375, 2045, 12149, 12402, 12403, 12413, +6 more
packages/budge/src/widget.tsx 379
6 setState calls in a single useEffect — consider using useReducer or deriving state · 10 in 4 files

no-cascading-set-state

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

File Lines
apps/website/app/__budge.tsx 445, 480, 493, 551
apps/website/components/budge-me-paper-preview.tsx 547, 751, 856
packages/budge/src/widget.tsx 744, 1082
apps/website/components/budge-logo.tsx 81
Component "TermsPage" is 350 lines — consider breaking it into smaller focused components · 8 in 6 files

no-giant-component

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

File Lines
apps/website/public/budge.iife.js 6373, 18209, 21644
apps/website/app/terms/page.tsx 8
apps/website/components/budge-me-paper-preview.tsx 489
apps/website/app/__budge.tsx 373
apps/website/components/replay/replay-viewer.tsx 375
…and 1 more file view on react.review
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 · 4 in 1 file

async-await-in-loop

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

File Lines
apps/website/components/budge-me-paper-preview.tsx 895, 895, 916, 933
Component "BudgeMePaperPreview" has 18 useState calls — consider useReducer for related state · 2 in 2 files

prefer-useReducer

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

File Lines
apps/website/components/budge-me-paper-preview.tsx 492
packages/budge/src/widget.tsx 655
t.memoizedProps.revealOrder is read 4 times inside this loop — hoist into a const at the top of the loop body · 2 in 1 file

js-cache-property-access

Hoist the deep member access into a const at the top of the loop body: const { x, y } = obj.deeply.nested

File Lines
apps/website/public/budge.iife.js 4099, 10318
.map().filter() 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
apps/website/public/budge.iife.js 12575
Component "Up" takes 4 boolean-like props (isProjecting, isProjectionDirty, isSharedProjectionDirty…) — consider compound components or explicit variants instead of stacking flags · 1 in 1 file

no-many-boolean-props

Split into compound components or named variants: <Button.Primary />, <DialogConfirm /> instead of stacking isPrimary, isConfirm flags

File Lines
apps/website/public/budge.iife.js 18998
Default prop value {} creates a new object reference every render — extract to a module-level constant · 1 in 1 file

rerender-memo-with-default-value

Move to module scope: const EMPTY_ITEMS: Item[] = [] then use as the default value

File Lines
apps/website/public/budge.iife.js 19326
new Intl.Segmenter() inside a function — hoist to module scope or wrap in useMemo so it isn't recreated each call · 1 in 1 file

js-hoist-intl

Hoist new Intl.NumberFormat(...) to module scope or wrap in useMemo — Intl constructors allocate dozens of objects per locale lookup

File Lines
apps/website/public/budge.iife.js 20039
[...array].sort() — use array.toSorted() for immutable sorting (ES2023) · 1 in 1 file

js-tosorted-immutable

Use array.toSorted() (ES2023) instead of [...array].sort() for immutable sorting without the spread allocation

File Lines
packages/budge/src/widget.tsx 372

Reviewed by reactreview for commit 087c34c. Configure here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions