Repository navigation
Description
Found by the #511 review round (PR #628), against web/src/components/usePagedList.ts. Not a #511 defect — the hook is unmodified by that PR and this behaviour affects all seven adopting screens equally (AuditPage, ExpensesPage, FeedPage, HistoryPage, SalesPage, StockPage, WaterPage, plus #511's three new ones).
1. A write during an in-flight extension can shrink the window
runWrite claims a new ticket before the write. If the user had a load-more extension in flight when the write started, that extension is superseded and its response discarded — correct so far. But refreshWindow then re-walks only up to cursorRef.current, which is the cursor as it stood before the abandoned extension. So rows the user could see are re-read away, and the newly written record can land in the gap between the refreshed window and where the user had actually paged to.
Every test across the hook and its adopters interleaves an entity/filter switch with a replacement in flight. None interleaves a write with an extension in flight, which is why this is unpinned.
2. A one-render window before reloading flips
The entity/filter identity changes synchronously in the handler, but the hook's reload runs from useEffect(() => void reload(), [reload]), which by React's contract runs after commit. So for one render the new heading can be painted beside the previous entity's rows. It is bounded to a single paint, the ticket still wins immediately afterwards, and it is identical for every existing adopter — screens that blank on reloading (#511's two ledgers) close it a render later, not synchronously. Pre-#511 InventoryPage happened to avoid it by calling setMovements([]) in the same handler as the id change.
Worth fixing only if a guaranteed zero-flicker switch is wanted; recorded so the next person does not re-derive it.
Suggested shape
For (1), refreshWindow should walk to the furthest cursor the user actually reached, not the cursor as of the superseded ticket. For (2), an optional synchronous clear on identity change, opt-in per screen.
Both need tests that interleave a write with an in-flight extension — the case the whole suite currently misses.
Related: #511, PR #628, #469 (the hook's original extraction).
Activity
fix(web): page truncated customer and movement tables with usePagedList
fix(web): retire the previous window when a replacement starts (#629)
fix(web): keep a paged window and an item panel on the user's newest …