fix(bindx-react): stabilize useEntityList selection identity to prevent refetch loop#39
Open
jindrak02 wants to merge 3 commits into
Open
fix(bindx-react): stabilize useEntityList selection identity to prevent refetch loop#39jindrak02 wants to merge 3 commits into
jindrak02 wants to merge 3 commits into
Conversation
…d selection identity
…nt refetch loop The options.selection path used the raw object reference for selectionMeta, which flowed into the data-loading effect's dependency array. Callers passing a content-identical-but-new selection object (e.g. DataGrid rebuilding its selection when children identity changes) triggered redundant backend queries, producing a self-sustaining /live request storm via fetch -> notify -> rerender. Unify both selection paths (definer 3rd-arg and pre-resolved options.selection) behind a single selectionRef keyed on the serialized query content. selectionMeta now keeps stable identity while the query content is unchanged, and effectiveQueryKey derives from that same content key. Legitimate refetches (changed fields without a queryKey, changed filter/orderBy/limit/offset, or a changed queryKey) still fire. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selectionContentKey is already the serialized query; wrapping it in another JSON.stringify produced a double-encoded string. Namespace it by entity type directly instead. Purely internal (effect dep / cache key) — no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #38
Problem
useEntityListre-fetched whenever the pre-resolvedselectionoption got a fresh object identity, even with identical content and a stablequeryKey. The definer path (3rd arg) was deliberately stabilized via a ref keyed on the serialized query; theoptions.selectionpath was not —selectionMetawas the raw reference and sat in the data-loading effect's dep array. SinceDataGridrebuildsselectionfrom thechildrenrender-prop on every render, a grid nested under a re-rendering store subscriber spun into an unbounded refetch loop (/liverequest storm, grid flickering "No results").Fix
Stabilize both selection paths identically.
useEntityList.ts— resolve the raw meta every render (fromdefineroroptions.selection), compute aselectionContentKey(serialized query), and only swap the ref'dselectionMetawhen that content key changes. Both paths now share one stabilization branch, so a new-but-content-identicalselectionobject keeps a stableselectionMetaidentity and the effect doesn't refire.effectiveQueryKeyis derived from the stableselectionContentKey(\${entityType}:\${contentKey}) instead of re-encoding viaselectionMeta, avoiding double JSON encoding.Test
tests/react/hooks/useEntityList/selectionIdentityRefetchLoop.test.tsx— aGridLikethat rebuilds a content-identicalselectionon a version bump while holding a stablequeryKey. One deliberate identity change must not trigger a second backend round-trip (queryCountstays1). Failed onmain(Received: 2), passes here. The version-controlled identity change keeps the test from livelocking on the very loop it guards.Test plan
bun test tests/react/hooks/useEntityList/selectionIdentityRefetchLoop.test.tsx— 1 passbun test tests/react/hooks/useEntityList/— 39 passbun run typecheck— clean