FirebaseExtended / FirebaseExtended/reactfire
Suspense mode resumes with the previous observable's value on React 19
- 主要言語
- TypeScript
- スター
- 3.6k
- フォーク
- 403
- 平均マージ
- 14時間 53分
- マージ済み PR(30日)
- 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