为何React.memo无法缓存组件?父组件仍重渲染的原因探究
React.memo缓存失效:Parent组件意外重渲染的原因
问题场景
我遇到了React.memo缓存失效的问题,具体代码如下:
子组件与父组件定义
function Child() { useEffect(() => { console.log("Child rerender"); }); return <div>Child component</div>; } function Parent({ children }: { children: React.ReactNode }) { useEffect(() => { console.log("Parent rerender"); }); return ( <div> Parent component {children} </div> ); }
组件缓存处理
const ChildMemo = React.memo(Child); const ParentMemo = React.memo(Parent);
顶层App组件
function App() { useEffect(() => { console.log("App rerender"); }); const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(count + 1)}>Update state {count}</button> <ParentMemo> <ChildMemo /> </ParentMemo> </> ); };
点击按钮触发App状态更新后,预期仅打印App rerender,但实际Parent组件也发生了重渲染。
原因分析
核心问题出在**children属性的引用变化**:
- React.memo默认使用浅比较判断是否需要重渲染,只有当props的引用完全不变时,才会复用缓存的组件实例。
<ChildMemo />是React.createElement(ChildMemo, null)的语法糖,每次App组件重渲染时,都会重新执行这个方法生成全新的React元素对象,也就是传递给ParentMemo的children属性每次都是新的引用。- 浅比较发现
children引用变化,因此ParentMemo会触发重渲染。
解决方案
要让ParentMemo的缓存生效,需保证传递给它的children引用稳定,有两种常用方式:
- 将子组件实例提到App组件外部
// 放在App组件外面,只会创建一次 const MemoizedChildInstance = <ChildMemo />; function App() { useEffect(() => { console.log("App rerender"); }); const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(count + 1)}>Update state {count}</button> <ParentMemo> {MemoizedChildInstance} </ParentMemo> </> ); };
- 使用useMemo缓存子组件实例
如果子组件依赖App的状态无法放到外部,可用useMemo缓存:
function App() { useEffect(() => { console.log("App rerender"); }); const [count, setCount] = useState(0); // 空依赖数组保证仅在组件挂载时创建一次 const memoizedChild = useMemo(() => <ChildMemo />, []); return ( <> <button onClick={() => setCount(count + 1)}>Update state {count}</button> <ParentMemo> {memoizedChild} </ParentMemo> </> ); };
内容的提问来源于stack exchange,提问作者tnsaturday
相关产品推荐
相关产品推荐

