Fast Refresh doesn't reset the React Compiler memo cache from c()
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 2/5
- 預估耗時
- 1-3 小時
- 新手友好度
- 82/100
- Issue 類型
- 缺陷
- 描述清晰度
- 描述清楚
- 活躍度
- 活躍
- 技術堆疊
- react, typescript
- 領域
- frontend
研究方向
從 src/react/compiler-runtime.ts 開始,檢查 c() 如何儲存其 memo 快取;將它與 src/dom/dispatcher.ts 中的 refresh 處理進行比較。將重現案例新增至 tests/fast-refresh.test.tsx,並確認更新後的元件在保留 state 的同時先顯示 after:1,再顯示 after:2。Issue 回報指出,採用建議的變更後,此測試和完整測試套件都能通過。
由索引模型根據 Issue 內容生成。
描述
Summary
After a Fast Refresh update, components compiled by React Compiler keep rendering their old output. The compiler runtime's c() keeps its memo cache across the refresh, so cached JSX from the previous version of the component is returned until a full reload.
React resets this cache on refresh. In development, renderWithHooks sets ignorePreviousDependencies when the fiber's type changed, and useMemoCache then refills the cache with sentinels (ReactFiberHooks.js).
Reproduction
Added to tests/fast-refresh.test.tsx. The component is written the way the compiler emits it:
import { c } from 'react/compiler-runtime'
it('resets the React Compiler memo cache but preserves state', () => {
function version(label: string) {
return function Example() {
const $ = c(3)
const [count, setCount] = useState(0)
let t0
if ($[0] === Symbol.for('react.memo_cache_sentinel')) {
t0 = () => setCount(n => n + 1)
$[0] = t0
} else t0 = $[0] as () => void
let t1
if ($[1] !== count) {
t1 = <button onClick={t0}>{label}:{count}</button>
$[1] = count
$[2] = t1
} else t1 = $[2]
return t1
}
}
const Before = version('before'), update = family(Before, 'stable')
const { container } = setup(<Before />)
click(container)
update(version('after'))
Refresh.performReactRefresh()
expect(container.textContent).toBe('after:1')
click(container)
expect(container.textContent).toBe('after:2')
})
On main it fails with expected 'before:1' to be 'after:1'.
Cause
c() in src/react/compiler-runtime.ts stores the cache in a useRef, which survives the refresh. useMemo and useCallback already handle this case: depsEqual returns false while the fiber is refreshing.
Babel's compiler hides the bug in development because it also emits a source-hash check that clears the cache whenever the file changes. The Rust port in oxc-transform-react, which @vitejs/plugin-react uses for react({ compiler: true }), doesn't emit that check, so with it every hot update of a compiled component is stale.
Suggested fix
Back c() with useMemo, so it picks up the existing refresh handling in depsEqual:
export function c(size: number): Array<unknown> {
return useMemo(() => new Array<unknown>(size).fill(MEMO_CACHE_SENTINEL), [size])
}
With this change the test above passes and the rest of the suite still passes (1860 passed, 91 skipped).
Versions
@tanstack/redact0.2.0, andmainat d56d87cbreact-refresh0.19.0 (from the test suite)oxc-transform-react0.155.0 with@vitejs/plugin-react6.1.2, where we first hit it
Disclaimer: this issue, including the reproduction test and the suggested fix, was researched and written by Claude, an AI assistant from Anthropic.
- 主要語言
- TypeScript
- 星號
- 408
- 分支
- 13
- 平均合併
- 1 小時 44 分鐘
- 30 天內合併 PR
- 21
環境準備
這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
TanStack/redact 的其他 Issue
-
難度 2/5 1-3 小時 新手友好度 85/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 88/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 90/100
TanStack/redact#67 · 1 個 reaction ·
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 82/100
維護者通常 1 天內回覆
相似的 Issue
-
area:plugins area:security area:skills bug has repro
難度 2/5 1-3 小時 新手友好度 76/100
anthropics/claude-code#105911 ·
維護者通常 1 天內回覆
-
openspec-apply-change skill: when blocked, may select a ready artifact unrelated to missingArtifacts未關閉
難度 2/5 1-3 小時 新手友好度 72/100
Fission-AI/OpenSpec#2165 ·
維護者通常 1 天內回覆
-
🐞 bug 🧐 unconfirmed
難度 2/5 1-3 小時 新手友好度 66/100
Tencent/tdesign-vue-next#7032 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 78/100
gnosis/gnosis_vpn#661 ·
維護者通常 1 天內回覆
-
content-freshness: staleOwnedContent doc comments still say 'complete receipt' (follow-up to #7912)未關閉triage:bug-verified
難度 1/5 1 小時以內 新手友好度 92/100
維護者通常 1 天內回覆