React.memo未生效:如何避免父组件渲染引发子组件重复渲染?
React.memo 失效:子组件随父组件状态更新重复挂载的解决方法
问题原因
你把Box组件定义在了Test组件内部。每次Test因为page状态变化重新渲染时,Box都会被重新创建成一个全新的函数。React会把这个新的Box识别为完全不同的组件类型,因此不会复用之前的组件实例,而是直接卸载旧组件、挂载新组件——这就是为什么useEffect的空依赖回调每次都会触发(挂载时执行),React.memo在这里完全起不到作用,因为组件类型已经变了。
修复方案
把Box组件移到Test组件外部,确保它不会随父组件渲染反复被重新定义:
import React from 'react'; // 将Box组件移到父组件外部,避免重复创建 const Box = () => { React.useEffect(() => console.info('Oh No..'), []); return <div>Box</div>; }; // 只创建一次MemoBox const MemoBox = React.memo(Box); function Test() { const [page, setPage] = React.useState(0); return ( <div> <MemoBox /> <button onClick={() => setPage(page + 1)}>Button</button> </div> ); } export default Test;
特殊场景的替代方案
如果必须在父组件内部定义子组件(比如需要访问父组件的状态或props),可以用useMemo缓存MemoBox,保证每次父组件渲染时它的引用不变:
import React from 'react'; function Test() { const [page, setPage] = React.useState(0); // 用useMemo缓存组件,空依赖确保只创建一次 const MemoBox = React.useMemo(() => { const Box = () => { React.useEffect(() => console.info('Oh No..'), []); return <div>Box</div>; }; return React.memo(Box); }, []); return ( <div> <MemoBox /> <button onClick={() => setPage(page + 1)}>Button</button> </div> ); } export default Test;
不过这种写法不推荐,除非有特殊需求,优先选择把组件移到外部的方案,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者HeonKyu Park
相关产品推荐
相关产品推荐

