[2.0 / next] <Errored> stays on its fallback after navigating away when a <Show>/<Match> condition read the failed fetch

未关闭
#4,644 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 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

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

solidjs/solid 的其他 Issue

查看 solidjs/solid 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。