[2.0 / next] <Errored> stays on its fallback after navigating away when a <Show>/<Match> condition read the failed fetch
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 35/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- typescript
- 领域
- frontend
调研方向
The failing spec is the vitest case built from the readers table in packages/web/test/, and the two control cases (text and For) pass, so start by comparing how the Show and Switch/Match readers consume the failed async memo. Run npx vitest run in packages/web to reproduce. Done means the Show and Switch/Match variants report about page after navigation while the controls still pass.
由索引模型根据 Issue 内容生成。
描述
Describe the bug
A list page reads an async memo, and the list fetch fails, so the <Errored> around the page shows its fallback. The user then navigates to another page, which is a different branch under the same <Errored>. If the list page read the failed memo in a <Show when> or a <Match when>, for example the usual empty-state check <Show when={rows().length === 0}>, the boundary keeps showing its fallback after the navigation, and the app stays on the error until a reload.
A plain read of the same memo (text, <For>, <Repeat>, an attribute, latest()) recovers on navigation. A wider sweep found the same failure for a memo of the condition used in a <Show>, for a keyed <Show>, and with or without a <Loading> around the page, and with the navigation done by <Show> or by <Switch>. Recovery by refresh() or by changing the memo's input works in every case.
Found by fuzzing reactivescript's example apps (a notes app whose list uses an empty-state <Show>), then reduced to plain Solid.
Your Example Website or App
The vitest spec below (in packages/web/test/), on next @ 42350195f.
Steps to Reproduce the Bug or Issue
import { render } from "@solidjs/web";
import { createMemo, createSignal, Errored, flush, For, Loading, Match, Show, Switch } from "solid-js";
import { expect, it } from "vitest";
const tick = async () => { for (let i = 0; i < 2; i++) { await new Promise(r => setTimeout(r, 0)); flush(); } };
type Row = { id: number };
const readers: Record<string, (rows: () => Row[]) => any> = {
"Show when={rows().length === 0}": rows => <Show when={rows().length === 0} fallback={<p>{rows().length} rows</p>}><p>no rows</p></Show>,
"Show when={rows()}": rows => <Show when={rows()}>{r => <p>{r().length} rows</p>}</Show>,
"Switch/Match": rows => <Switch fallback={<p>{rows().length} rows</p>}><Match when={rows().length === 0}><p>no rows</p></Match></Switch>,
"text (control)": rows => <p>{rows().length} rows</p>,
"For (control)": rows => <ul><For each={rows()}>{r => <li>{r.id}</li>}</For></ul>,
};
for (const [name, view] of Object.entries(readers))
it(`${name}: navigating away from a failed list clears <Errored>`, async () => {
let rejectList!: (e: Error) => void;
const el = document.createElement("div");
let setPage!: (p: string) => void;
const dispose = render(() => {
const [page, set] = createSignal("list"); setPage = set;
const rows = createMemo(() => new Promise<Row[]>((_, reject) => { rejectList = reject; }));
return (
<Errored fallback={<p>could not load</p>}>
<Show when={page() === "list"} fallback={<p>about page</p>}>
<Loading fallback={<p>loading</p>}>{view(rows)}</Loading>
</Show>
</Errored>
);
}, el);
await tick();
rejectList(new Error("boom")); await tick();
const failed = el.textContent;
setPage("about"); flush(); await tick();
const after = el.textContent;
dispose();
expect({ failed, after }).toEqual({ failed: "could not load", after: "about page" });
});
npx vitest run in packages/web. The two control tests pass; the Show and Switch/Match tests fail with after: "could not load".
Expected behavior
After navigating away, nothing under the boundary reads the failed memo, so <Errored> renders the new branch (about page), as it does when the list page reads the memo as text or in a <For>.
Platform
- OS: macOS
- Browser: n/a (jsdom)
- Version: solid-js 2.0.0-rc.20,
next@ 42350195f
- 主要语言
- TypeScript
- 星标
- 36.2k
- 派生
- 1.1k
- 平均合并
- 10 小时 39 分钟
- 30 天内合并 PR
- 500
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
solidjs/solid 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 35/100
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 55/100
维护者通常 1 天内回复
-
[2.0 / next] Optimistic todo list with an "N left" memo loops forever when a toggle's save lands未关闭
难度 5/5 一周以上 新手友好度 15/100
维护者通常 1 天内回复
-
[2.0 / next] createOptimisticStore: add, delete, add with saves pending hands <For> an undefined row未关闭
难度 4/5 3-5 天 新手友好度 25/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 18/100
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 82/100
维护者通常 1 天内回复
-
needs-area
难度 2/5 1-3 小时 新手友好度 68/100
Azure/typespec-azure#5936 ·
维护者通常 1 天内回复
-
难度 2/5 半天 新手友好度 72/100
vercel-labs/scriptc#2910 ·
维护者通常 1 天内回复
-
automation missing-model model-sync provider:fireworks-ai
难度 2/5 1-3 小时 新手友好度 72/100
anomalyco/models.dev#12458 ·
维护者通常 1 天内回复