FirebaseExtended / FirebaseExtended/reactfire

Suspense mode resumes with the previous observable's value on React 19

未关闭
#793 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
v5
主要语言
TypeScript
星标
3.6k
派生
403
平均合并
14 小时 53 分钟
30 天内合并 PR
5

描述

`useObservable` in suspense mode suspends correctly when the observable and `observableId` are swapped, then resumes rendering the **previous** observable's value.

Found by the first test run ever executed against React 19 (#789); nothing had run against 19 before, only type-checks.

## Reproduction

`test/useObservable.test.tsx`, `emits the new observable's value if the observable is swapped out`. The test renders a component under `React.Suspense`, emits `Jeff` on the first observable, swaps both the observable and the `observableId`, rerenders, then emits `James` on the second.

- **React 18.2.0:** the fallback shows, then the component resumes with `James`. Passes.
- **React 19.2.8:** the fallback shows (that assertion passes), then the component resumes with `Jeff`. Fails.

Deterministic: 3 runs each way, same `@testing-library/react` 16.3.2, only the React runtime swapped via `npm install --no-save react@19 react-dom@19`. No emulators involved, so `npx vitest run useObservable` reproduces it.

## What is known and not known

- The suspend half works. Only the resume is wrong, so this is not the known throw-vs-`use()` question: the 08-07 spike found the `use()` swap is a behavioural no-op on 19 and that React 19 emits no warning for the current throw form. Nothing here contradicts that.
- **The cause is not diagnosed.** The plumbing involved (`SuspenseSubject`, the `preloadedObservables` cache keyed by `observableId`, and the `use-sync-external-store` shim delegating to React's own `useSyncExternalStore` on 19) overlaps what #790 covers, but no connection has been established and it should not be assumed.

## Current state

#789's CI PR skips this test on React 19 only, so the new test job can land green. The skip is a `? it.skip : it` ternary rather than `it.skipIf`, because these globals are typed by `@types/jest` and `skipIf` fails `tsc` while working at runtime.

Restore it to a plain `it` when this is fixed.

贡献指南

打开贡献指南

调研方向

Run `npx vitest run useObservable` and start with `test/useObservable.test.tsx`, especially `emits the new observable's value if the observable is swapped out`. Trace the named `SuspenseSubject`, `preloadedObservables` cache, and `use-sync-external-store` path. Done means the test is restored to plain `it` and passes under React 19 while retaining the React 18 behavior.

由索引模型根据 Issue 内容生成。

评估

技术栈
react, typescript
领域
frontend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
48/100

把新 issue 发到你的邮箱

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