2.0.0-rc.20: <Loading> stays on its fallback forever when an async memo's first answer is superseded while a sibling under the same boundary refetches
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 25/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- typescript
- Ambito
- frontend
Direzione di ricerca
Start by running the reproduction as a Vitest test with jsdom, and confirm that the control case passes while the sibling-refetch case shows <p>wait</p>. The bug sits in how a Loading boundary tracks pending async memos when a first promise is superseded by a synchronous recomputation, so the fix lives in the reactive core, not in the components shown. Done means both cases in the repro render <i>B</i><b>A</b> and the boundary recovers after later writes.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
Two async memos a and b are read under one <Loading>. b is on its first load. While it loads, a starts a refetch (returns a new promise). b's first answer then lands in the order data libraries use: the value is stored and the memo's source is bumped before the first promise's continuation reaches the core, so the first flight is superseded by a synchronous recomputation. a's refetch then settles.
Both memos now hold settled values, but <Loading> shows its fallback forever. Without the sibling refetch the same sequence renders the content.
- rc.13: renders
""(also wrong) - rc.20:
<p>wait</p>forever - next@215c365:
<p>wait</p>forever
Steps to Reproduce
Same setup as above. repro.test.tsx:
import { render } from "@solidjs/web";
import { createMemo, createSignal, Loading, Show } from "solid-js";
import { expect, it } from "vitest";
const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));
async function run(refetchA: boolean): Promise<string> {
const [aVersion, setAVersion] = createSignal(0);
const [bVersion, setBVersion] = createSignal(0);
let aFlight: Promise<string> | null = null;
let releaseA: (v: string) => void = () => {};
let bValue: string | null = null;
let releaseB: (v: string) => void = () => {};
const bFlight = new Promise<string>((resolve) => (releaseB = resolve));
const el = document.createElement("div");
const dispose = render(() => {
const a = createMemo(() => (aVersion(), aFlight ?? "A"));
const b = createMemo(() => (bVersion(), bValue ?? bFlight.then((v) => v)));
return (
<Loading fallback={<p>wait</p>}>
<Show when={b()}>
<i>{b()}</i>
</Show>
<Show when={a()}>
<b>{a()}</b>
</Show>
</Loading>
);
}, el);
await wait(10);
expect(el.innerHTML).toBe("<p>wait</p>");
if (refetchA) {
aFlight = new Promise<string>((resolve) => (releaseA = resolve));
setAVersion(1);
}
await wait(0);
// b's first answer: the value is written and its version bumped before the
// first promise's continuation reaches the core (the order TanStack Query uses).
bValue = "B";
releaseB("B");
setBVersion(1);
await wait(20);
if (refetchA) {
aFlight = null;
releaseA("A");
setAVersion(2);
}
await wait(50);
const html = el.innerHTML;
dispose();
return html;
}
it("control: without a sibling refetch the content renders", async () => {
expect(await run(false)).toBe("<i>B</i><b>A</b>");
});
it("with a sibling refetch in the same window the content renders once both settle", async () => {
expect(await run(true)).toBe("<i>B</i><b>A</b>");
});
package.json
{
"name": "solid-repro",
"private": true,
"type": "module",
"scripts": { "test": "vitest run" },
"dependencies": {
"solid-js": "2.0.0-rc.20",
"@solidjs/web": "2.0.0-rc.20",
"@solidjs/signals": "2.0.0-rc.20"
},
"devDependencies": {
"@solidjs/vite-plugin": "3.0.0-next.54",
"jsdom": "30.1.2",
"vitest": "5.0.5"
}
}
vitest.config.ts
import solid from "@solidjs/vite-plugin";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [solid()],
test: { environment: "jsdom" },
});
Expected behavior
<i>B</i><b>A</b> in both cases.
Actual behavior
Control passes; with the sibling refetch the boundary stays at <p>wait</p> and never recovers (no further writes revive it).
Platform
As above.
- Lingua principale
- TypeScript
- Stelle
- 36.2k
- Fork
- 1.1k
- Merge medio
- 11h 5m
- PR unite (30g)
- 475
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di solidjs/solid
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 28/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 12/100
I maintainer di solito rispondono entro 1 giorno
-
[2.0 / next] <Errored> recovery shows a pending memo's answer to an older input beside the new inputAperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 20/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 18/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di solidjs/solid
Issue simili
-
Remove unused dependenciesForse già presa @alastair-smith l’ha presa oggi. Apertachore other
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
alastair-smith/card-games#384 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
code-yeongyu/senpi#5571 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
nexu-io/open-design#9262 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
friction
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
kentcdodds/kody#4753 ·
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
lingdojo/kana-dojo#33508 · 1 commento · 5 reazioni ·
I maintainer di solito rispondono entro 1 giorno