未使用useCallback时,React.memo为何无法阻止组件重渲染?
问题解析:React.memo为何无法阻止组件重渲染
示例代码
function App(){ const [count,setCount]=useState(0); function countUp(){ setCount(count=>count+1); } function countDown(){ setCount(count=>count-1); } return( <div> <p>count:{count}</p> <AppTwo countUp={countUp} countDown={countDown}/> </div> ) } const AppTwo=React.memo(({countUp, countDown})=>{ useEffect(()=>{ console.log('re-rendering.') }) return( <div> <button onClick={countUp}>count UP</button> <button onClick={countDown}>count DOWN</button> </div> ) })
核心原因
这本质是JavaScript中函数的引用特性导致的:
- 在JavaScript里,函数属于引用类型,每次创建新函数(比如App组件每次渲染时定义的
countUp、countDown),都会在内存中生成全新的引用地址。 - React.memo默认采用浅比较判断组件是否需要重渲染:对比前后两次props时,会检查每个prop的引用是否一致。
- 每次App组件因
count变化重渲染时,都会重新创建countUp和countDown函数,新函数的引用和上一次完全不同。React.memo发现props里的函数引用变了,就会判定“props发生变化”,进而触发AppTwo的重渲染。
解决办法
用useCallback钩子缓存函数引用:
function App(){ const [count,setCount]=useState(0); // 用useCallback缓存函数,依赖项为空(因为函数内部用了函数式更新,不依赖外部count) const countUp = useCallback(() => { setCount(count=>count+1); }, []); const countDown = useCallback(() => { setCount(count=>count-1); }, []); return( <div> <p>count:{count}</p> <AppTwo countUp={countUp} countDown={countDown}/> </div> ) }
只要useCallback的依赖数组不变,每次App渲染时都会返回同一个函数引用,React.memo对比props时会认为函数没变化,就能成功阻止AppTwo的不必要重渲染。
内容的提问来源于stack exchange,提问作者Sein kim
相关产品推荐
相关产品推荐

