memo
如下所示例子中,因为App内部状态的更新,总会牵连其无辜子组件Demo的更新。
const Demo = () => {console.log('Demo render');return (<div>我是子组件</div>);
};const App = () => {console.log('App render');const [count, setCount] = useState(0);const doInc = () => {setCount(count + 1);};return (<><div>{count}</div><button onClick={doInc} className='bg-blue-400 p-1 rounded text-white'>改变组件</button><hr className='mt-2'/><Demo /></>);
};
如何避免呢? 其实官方已经提供了这个优化的方案,那就是使用memo,你仅仅且包裹住这个组件即可!
const Demo = memo(() => {console.log('Demo render');return (<div>我是子组件</div>);
});
memo的作用就是对比组件重新render前后的 **props是否发生变化*:如果没有发生变化,则不会重新render。
但是注意他仅比较基本类型,如果是对象则会比较引用地址,如下则每次还都会重新render:
const Demo = memo((props) => {console.log('Demo render');return (<div>我是子组件</div>);
});const App = () => {console.log('App render');const [count, setCount] = useState(0);const doInc = () => {setCount(count + 1);};const info = {title: '子组件'};return (<><div>{count}</div><button onClick={doInc} className='bg-blue-400 p-1 rounded text-white'>改变组件</button><hr className='mt-2'/><Demo info={info}/></>);
};
原因也很简单,因为每次App组件的重新render,就会导致info是一个新创建的对象,引用地址自然就不同了!
解决办法:使用useMemo包裹住这个对象即可,这样这个对象就会被缓存下来不会被App重建!
const Demo = memo((props) => {console.log('Demo render');return (<div>我是子组件</div>);
});const App = () => {console.log('App render');const [count, setCount] = useState(0);const doInc = () => {setCount(count + 1);};const info = useMemo(()=>({title: '子组件'}),[]);return (<><div>{count}</div><button onClick={doInc} className='bg-blue-400 p-1 rounded text-white'>改变组件</button><hr className='mt-2'/><Demo info={info}/></>);
};
tips: useMemo一般用于缓存对象,如果是函数react还提供了useCallback,作用一样!