FirebaseExtended / FirebaseExtended/reactfire
Suspense mode resumes with the previous observable's value on React 19
- Ngôn ngữ chính
- TypeScript
- Star
- 3.6k
- Fork
- 403
- Merge trung bình
- 14 giờ 53 phút
- Pull request đã merge (30 ngày)
- 5
Mô tả
`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.
Hướng dẫn đóng góp
Hướng nghiên cứu
Chạy `npx vitest run useObservable` và bắt đầu với `test/useObservable.test.tsx`, đặc biệt là `emits the new observable's value if the observable is swapped out`. Theo dõi `SuspenseSubject` được nêu tên, bộ nhớ đệm `preloadedObservables` và đường dẫn `use-sync-external-store`. Được xem là hoàn tất khi test được khôi phục về `it` thông thường và chạy đạt trên React 19, đồng thời vẫn giữ nguyên hành vi của React 18.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- react, typescript
- Lĩnh vực
- frontend
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 48/100