这篇文章将讲解 useCallback, useMemo 及 React.Memo 的运行时,作用,使用场景和注意事项
useCallback()
- 作用
useCallback 的真正目的在于缓存了每次渲染时 inline callback 的实例
配合 shouldComponentUpdate 或 React.memo 起到减少不必要的渲染的作用
本质优化子组件的渲染次数 - 运行时
返回 memoized 函数的引用
依赖参数改变 useCallback 返回 新的的引用地址否则返回上一次回调函数的引用
当引用相等时返回缓存结果, 引用不等时重新计算结果返回 - 使用(2步)
1 一个方法作为 props 传递给子组件的时候 使用 useCallback 包裹此方法,
2 使用 React.memo 包裹子组件
const A = ()=>{
cosnt aFun = useCallback(()=> {
console.log('方法被调用')
},[])
return (
<div>
<B cb={aFun}/>
</div>
)
}
const B = memo(({cb})=>{
return (
<button onClick={cb}> </button>
)
})
useMemo()
- 作用
用于针对于当前组件高开销的计算 因为 useMemo() 具有记忆功能,也就是缓存能力,这可以避免在函数的依存关系未改变的情况下重新渲染。useMemo() 的功能相当于 vue 的 computed - 运行时
返回一个 memoized 值
依赖关系改变返回重新计算的结果, 否则返回缓存结果
函数内部引用的每个值都应出现在依赖关系数组中 - 使用
const ComputeComponent = () => {
const [count, setCount] = useState(100);
const [changeNum, setChangeNum] = useState(100);
// 这里使用 useMemo 缓存计算结果,当依赖改变重新计算结果
const computeValue = useMemo(() => computeExpensiveValue(count), [count]);
function computeExpensiveValue(count) {
console.log('computeExpensiveValue 被执行');
//假设比较大计算的计算开销非常大
const array = new Array(count).fill(count);
return array.reduce((currentTotal, item) => {
return currentTotal + item;
}, 0);
}
// 点击 handleSetCount 的时候 computeValue 使用缓存结果
const handleSetCount = () => {
setCount(preCount => preCount * 2);
};
// 点击 handleChangeNum 的时候 computeValue 重新计算结果
const handleChangeNum = () => {
setChangeNum(preCount => preCount * 2);
};
return (
<div>
<div>{computeValue}</div>
// 使用缓存
<div onClick={handleSetCount}>addCount{count} </div>
// 重新计算
<div onClick={handleChangeNum}> add changeNum {changeNum}</div>
</div>
);
};
React.Memo
- 作用
使普通的函数组件(PureComponent) 拥有与 shouldComponentUpdate 相同得能力 - 用法
参考 useCallback() 使用示例 - 运行时
在 props 更改时 才会触发重新 渲染
useMemo 与 React.Memo 的区别
- React.memo() 是一个HOC,用来包装那些我们不想重新渲染的组件,除非它们 props 发生了变化
- useMemo()是一个React Hook,在组件中我们可以用它包裹函数或值。被包裹函数(值)的一个依赖项发生变化时才重新计算该函数中的数据
useCallback 与 useMemo的区别
- useCallback 优化针对于子组件渲染
- useMemo 优化针对于当前组件高开销的计算
注意:
- 虽然 useMemo 和 React.memo 看起来像是在任何地方都可以使用的妙招,但是只应该在绝对需要性能提升时才使用它。因为 memo 会占用机器上的内存空间,因此可能会导致意外的效果。
- 性能优化不是免费的。 它们总是带来成本,但这并不总是带来好处来抵消成本。
- 大多数时候,不需要考虑去优化不必要的重新渲染。React是非常快的,可以利用时间去做很多事情,比起做这些类似的优化要好得多