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.tsx → VouchersView
Steps to reproduce
- Use an account that has many vouchers (e.g. 300+) on Base Sepolia.
- Connect the wallet in the UI (pointing at the Fly.io-hosted rollups endpoint as configured).
- Open My Collections (
/collections).
- 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)
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 repeatedsetState/ hook updates in a tight loop. The page becomes unusable at this scale.Environment
jam-ui)jam-ui(Comet)apps/jam-ui/src/app/collections/page.tsx→VouchersViewSteps to reproduce
/collections).Expected behavior
Actual behavior
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.Technical notes (for maintainers)
Relevant code paths:
apps/jam-ui/src/components/vouchers/VouchersView.tsxVoucherListusesuseMemo(..., userVouchers)without wrapping in a single-element dependency array ([userVouchers]). The second argument touseMemois a dependency list; passing the vouchers array directly can be interpreted as one dependency per array element, which is fragile at 300+ items.ExecuteButton, which mounts multiple wagmi hooks per voucher (useReadCartesiApplicationWasOutputExecuted,useSimulateCartesiApplicationExecuteOutput, etc.).MintVouchercallsuseFindJamper mint voucher, multiplying concurrent queries when many mint vouchers exist.apps/jam-ui/src/components/vouchers/queries.tsxuseGetUserVouchersusesuseOutputswithOUTPUTS_LIMIT = 200andoffset: 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
useMemodependency misuse may drive excessive re-renders or update cascades.Suggested directions (not prescriptive)
useMemodependencies inVoucherList(e.g.[userVouchers]).useFindJamusage for mint rows (batch or cache jam metadata).useOutputslimit/offsetwith real max collection size and document limits in the UI.Acceptance criteria (proposal)
/collectionsloads without React "maximum update depth" errors with ≥ 300 vouchers (or product-defined max).