Skip to content

test(solid-query): pin the stale read through a memo over query.data (#11351) 🤖🤖🤖 - #11357

Open
mgarcialeniolabs wants to merge 1 commit into
TanStack:solid-query-v6-prefrom
mgarcialeniolabs:issue-11351
Open

test(solid-query): pin the stale read through a memo over query.data (#11351) 🤖🤖🤖#11357
mgarcialeniolabs wants to merge 1 commit into
TanStack:solid-query-v6-prefrom
mgarcialeniolabs:issue-11351

Conversation

@mgarcialeniolabs

Copy link
Copy Markdown

🎯 Changes

Adds a reproduction for #11351 to useQuery-semantics.test.tsx, in the data store face block.

A tracked computation that reaches a leaf through a createMemo(() => query.data) indirection
is not re-notified after a refetch, so its last observation stays the superseded value permanently.
A wrapper hook that gates or narrows query.data before handing it to consumers is exactly this
shape, so it reaches app code that never writes the memo explicitly.

The test is added as it.skip, following the existing convention in useQuery.test.tsx for a
documented divergence, because the fix is not in this repo — see below. Un-skipped it fails on
the last assertion only, after expect(rendered.getByText('flag: true')) has already passed: the
commit lands and the DOM swaps, and only the reader behind the memo is starved.

Why no fix here

The data node is not at fault. computeData runs exactly the expected four times across mount and
refetch, chainOnce produces one chained promise per fetch with no identity churn, the commit
lands, an untracked read through the very same memo returns the new value, and neither the memo nor
the data node is left isPending. Only the notification to one reader shape is lost.

Narrowing across reader shapes (all against the real hook):

Reader shape Result
effect reads query.data.flag pass
memo reads query.data.flag, effect reads the memo pass
effect captures query.data via untrack, then reads .flag off it pass
effect depends on a suspended memo over an unrelated async source, reads query.data.flag pass
memo reads query.data, effect reads memo().flag fail
memo reads query.data, effect reads both query.data and memo().flag fail

Row 6 is the one that rules out a missing subscription: the effect reads the projection directly
and depends on the memo, and is still not notified. Row 4 rules out "any suspended memo
dependency" — the memo has to be a consumer of this projection. A memo created after the first
settle is fine; only one that suspended on its first run is affected.

The behaviour reproduces with no TanStack code involved, so I filed it upstream:
solidjs/solid#3181. 2.0.0-rc.4 is the newest published solid-js / @solidjs/signals, so
there is no version bump that fixes it.

The workarounds I tried and rejected, in case they come up in review:

  • Making the committed value's identity change per commit so the memo propagates — that is
    reconcile-off, and discards the fine-grained leaf tracking pinned by 'tracks deep reads at the leaf — unrelated changes do not re-run them'.
  • Returning a stable re-reading facade from get data() — works only if the getter drops its
    suspending read, which would stop query.data suspending into <Loading> and break primitive
    and array data.
  • Not returning the promise on refetch, to avoid the hold — deletes the SWR hold semantics covered
    by transition.test.tsx.
  • Not superseding the in-flight answer with a synchronous value at settle (a landed flag on
    chainOnce, returning the unlanded chained promise instead of wrap(state.data)) — tried and
    reverted
    : it does not fix the reproduction and it breaks 'keeps stale data and exposes error state when a refetch fails'.

Happy to drop the skipped test and just leave the narrowing on the issue instead, if you'd rather
not carry it.

Note on base branch: this targets solid-query-v6-pre, since the rc.1 code the issue is about
does not exist on main.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm run test:pr, or these tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

Verified locally from the repo root:

pnpm nx run @tanstack/solid-query:test:lib      # 26 files, 346 passed, 2 skipped, no type errors
pnpm nx run @tanstack/solid-query:test:eslint   # clean

Baseline on solid-query-v6-pre before this change is 346 passed / 1 skipped, so the only delta is
the added skipped test.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Made with Cursor

A tracked computation that reaches a leaf THROUGH a
`createMemo(() => query.data)` indirection is not re-notified after a refetch,
so its last observation stays the superseded value permanently. A wrapper hook
that gates or narrows `query.data` before handing it to consumers is exactly
this shape, so it reaches app code that never writes the memo explicitly.

The data node is not at fault: the derive runs the expected number of times,
the commit lands, the DOM swaps, and an untracked read through the very same
memo returns the new value. Every other reader shape is notified correctly,
and the behaviour reproduces with no TanStack code involved, so the test is
skipped pending the upstream fix in solidjs/solid#3181.

Refs TanStack#11351

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 91306f7e-2be6-455c-9168-e10da02ceae9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants