Skip to content

Collections: Maximum update depth exceeded with 300+ vouchers (Base Sepolia) #18

@riseandshaheen

Description

@riseandshaheen

Summary

On the My Collections page (/collections), loading 300+ vouchers triggers a client-side React error: Uncaught Error: Maximum update depth exceeded, which usually indicates repeated setState / hook updates in a tight loop. The page becomes unusable at this scale.

Environment

  • Network: Base Sepolia
  • Rollups node: Hosted on Fly.io (Cartesi Rollups HTTP endpoint used by jam-ui)
  • App: jam-ui (Comet)
  • Page: Collections — apps/jam-ui/src/app/collections/page.tsxVouchersView

Steps to reproduce

  1. Use an account that has many vouchers (e.g. 300+) on Base Sepolia.
  2. Connect the wallet in the UI (pointing at the Fly.io-hosted rollups endpoint as configured).
  3. Open My Collections (/collections).
  4. Observe the browser console and page behavior.

Expected behavior

  • The collections list loads (possibly with loading state).
  • UI remains stable; user can scroll and interact (execute vouchers, etc.), or sees a clear limit/pagination message if the product caps batch size.

Actual behavior

  • Error: Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
  • Collections view does not behave correctly at this voucher count.

Technical notes (for maintainers)

Relevant code paths:

  • apps/jam-ui/src/components/vouchers/VouchersView.tsx
    • VoucherList uses useMemo(..., userVouchers) without wrapping in a single-element dependency array ([userVouchers]). The second argument to useMemo is a dependency list; passing the vouchers array directly can be interpreted as one dependency per array element, which is fragile at 300+ items.
    • Each row renders ExecuteButton, which mounts multiple wagmi hooks per voucher (useReadCartesiApplicationWasOutputExecuted, useSimulateCartesiApplicationExecuteOutput, etc.).
    • MintVoucher calls useFindJam per mint voucher, multiplying concurrent queries when many mint vouchers exist.
  • apps/jam-ui/src/components/vouchers/queries.tsx
    • useGetUserVouchers uses useOutputs with OUTPUTS_LIMIT = 200 and offset: 0 — at 300+ vouchers, outputs may be incomplete or the UI still attempts to render a very large list; consider pagination / higher limits / alignment with RPC.

Hypothesis (non-exclusive): Scale of simultaneous hooks + query subscriptions + possible useMemo dependency misuse may drive excessive re-renders or update cascades.

Suggested directions (not prescriptive)

  • Fix useMemo dependencies in VoucherList (e.g. [userVouchers]).
  • Virtualize or paginate the collections list so DOM and hook count stay bounded.
  • Throttle / batch per-voucher chain reads and execution prep (or lazy-load Execute when in view).
  • Revisit useFindJam usage for mint rows (batch or cache jam metadata).
  • Align useOutputs limit / offset with real max collection size and document limits in the UI.

Acceptance criteria (proposal)

  • /collections loads without React "maximum update depth" errors with ≥ 300 vouchers (or product-defined max).
  • Clear UX if a hard cap exists (pagination, "load more," message).

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions