Probleem
De infinite-loop lesson van T426404 zegt: in een useEffect met een array-dep moet setState((prev) => prev.map(...)) prev retourneren wanneer geen element gemuteerd is — anders triggert de nieuwe array-referentie een nieuwe render → nieuwe effect-run → loop.
In de codebase is dit nu correct toegepast in de category-check (src/app.jsx:643-668 heeft een changed-flag). Twee andere effects volgen het patroon niet consistent:
- stashRefilledRef effect (src/app.jsx:475-513) — geen changed-flag, en de Set groeit oneindig (slinkt nooit als items leeg raken).
- dupCheckedRef effect (src/app.jsx:524-555) — geen cancelled cleanup; geen changed-flag bij setItems binnen resolve. Werkt vandaag omdat <App> nooit unmount, maar fragiel bij toekomstige component-splitting.
Suggestie
- Beide effects: zelfde changed-flag-patroon als de category-check.
- dupCheckedRef: voeg let cancelled = false; return () => { cancelled = true; }; cleanup toe.
- stashRefilledRef: bij stash empty → clear de Set (of refactor naar sha1-based keying, in lijn met de T425756 lesson).
Acceptance
- Beide effects retourneren prev (zelfde referentie) wanneer geen rij muteert
- Geen latente loop bij snel wisselende item-arrays