Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

solid-query: EFFECT_RELAY_TEAR on Solid 2 when a query key changes — useBaseQuery relays the result through a version signal written from a render effect

Offen
#11,903 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@S-jooyoung arbeitet bereits daran.

Seit 19.10.2026.

  • #12126 von @S-jooyoung — offen

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
45/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
typescript
Bereich
frontend

Rechercherichtung

The adapter's useBaseQuery (the payload points at build/index.js) wires createRenderEffect(() => defaultedOptions(), opts => observer.setOptions(opts)), then relays cache events into a version signal read by query. Start by reproducing the key switch with the issue's captureArtifact snippet under vitest/jsdom and confirming EFFECT_RELAY_TEAR. Trace whether the observer result can be derived as a memo or projection of the current options instead of a counter written from onCacheEvent; done means the diagnostic no longer fires and query.data shows the new key's value in the same flush.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Describe the bug

With Solid 2 ([email protected]) and @tanstack/[email protected] (the useBaseQuery code is identical in 6.0.0-rc.5), switching the query key of a useQuery logs a reactivity diagnostic from @solidjs/[email protected]:

[EFFECT_RELAY_TEAR] memo "computed" ran twice for one write of "tariff": once in the flush where "tariff" changed,
and again after effect "effect" relayed it by writing "signal" — the first frame showed the new "tariff" with the stale "signal".
If "signal" is computed from what the effect reads, make it a memo so readers get it in the same flush;
if the write reads something outside the graph (layout, time), the tear is the cost of measuring.

Owner path: <QueryClientProvider> › <provider> › computed › <Price> › computed — the only user code is a createMemo reading query.data. One diagnostic per useQuery instance whose key changed (a screen with five queries logs five).

Solid 2 dev builds treat these diagnostics as actionable (the console is expected to stay clean), so every app that derives anything from query.data and ever changes a key gets a warning it cannot fix on its side.

Where it comes from

useBaseQuery (build/index.js):

createRenderEffect(
  () => defaultedOptions(),
  (opts) => observer.setOptions(opts)
);
const [version, setVersion] = createSignal(0, { ownedWrite: true });
const onCacheEvent = (event) => {
  if (event.query.queryHash === untrack(defaultedOptions).queryHash || event.query.queryHash === latestHash) {
    setVersion((v) => v + 1);
  }
};
...
const query = () => {
  version();
  return lookupQuery();
};

When the key changes, defaultedOptions is recomputed in the same flush as the key signal; readers of query.data see the new options with the old observer result, then the render effect calls observer.setOptions, the cache event bumps version, and every memo downstream recomputes a second time. That is exactly the "effect relays a derived value by writing a signal" pattern the diagnostic describes: version is derived from what the effect reads, so the first frame is torn.

Your minimal, reproducible example
import { captureArtifact } from '@solidjs/diagnostics';
import { render } from '@solidjs/testing-library';
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/solid-query';
import { createMemo, createSignal, flush } from 'solid-js';

function Price(props: { tariff: string }) {
  const query = useQuery(() => ({ queryKey: ['price', props.tariff], queryFn: async () => props.tariff.length }));
  const doubled = createMemo(() => (query.data ?? 0) * 2);
  return <span>{doubled()}</span>;
}

const client = new QueryClient({ defaultOptions: { queries: { staleTime: Infinity, retry: false } } });
client.setQueryData(['price', 'base'], 1);
client.setQueryData(['price', 'site'], 2);
const [tariff, setTariff] = createSignal('base');

const { artifact } = await captureArtifact(async () => {
  const screen = render(() => (
    <QueryClientProvider client={client}>
      <Price tariff={tariff()} />
    </QueryClientProvider>
  ));
  flush();
  setTariff('site');          // key change
  flush();
  await new Promise((r) => setTimeout(r, 30));
  flush();
  screen.unmount();
}, { scenario: 'useQuery key switch', attribution: true });

console.log(artifact.diagnostics.map((e) => e.code)); // ['EFFECT_RELAY_TEAR']

Both keys are already in the cache, so no fetch is involved — the second recompute is purely the version relay.

Steps to reproduce
  1. Mount a component with useQuery whose key depends on a signal, and a createMemo reading query.data.
  2. Change the signal (with @solidjs/diagnostics capturing, attribution on).
  3. Observe EFFECT_RELAY_TEAR for the memo.
Expected behavior

Changing a query key should produce one consistent frame: the result for the new key arrives in the same flush as the key (e.g. the observer result derived as a memo / projection of the options instead of being relayed through a counter signal written from a cache subscription), or the diagnostic should not fire for useQuery consumers.

Platform
TanStack Query adapter

solid-query

TanStack Query version

6.0.0-rc.4 / 6.0.0-rc.5

TypeScript version

7.0

Additional context

Related: #11358 (STRICT_READ_UNTRACKED in the same adapter under Solid 2 diagnostics).

Vorherrschende Sprache
TypeScript
Sterne
50.4k
Forks
4.3k
Ø Merge
11 Std. 37 Min.
Gemergte PRs (30 T.)
521

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus TanStack/query

Alle Issues in TanStack/query

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.