useMemo
useMemo 用于做性能优化,Memo 是 memoized(记忆)的简写
useMemo 返回的是一个缓存的值,可以避免其在组件更新时就被重新计算,而是在它的依赖项改变时才重新计算
下面来看示例,将 App.tsx 文件内容替换为下面的代码:
import React from "react";
import "./App.css";
const App: React.FC = () => {
const [count, setCount] = React.useState(0);
const [countMemo, setCountMemo] = React.useState(0);
const getCount = () => {
console.log("getCount");
return count;
};
const getCountMemo = React.useMemo(() => {
console.log("getCountMemo");
return countMemo;
}, [countMemo]);
return (
<>
<h1>count:{getCount()}</h1>
<button onClick={() => setCount((count) => count + 1)}>Add Count</button>
<h1>countMemo:{getCountMemo}</h1>
<button onClick={() => setCountMemo((countMemo) => countMemo + 1)}>Add CountMemo</button>
</>
);
};
export default App;
点击 Add Count ,可以看到日志打印了多次 getCount,没有 getCountMemo
点击 Add CountMemo ,可以看到每次都打印了 getCount 和 getCountMemo
对比可得,getCountMemo 只有依赖项变化,才会重新计算缓存值,而 getCount 在每次页面重新渲染时,都会重新执行
举一个实际的例子,比如现在父组件传给子组件属性 A、B、C,子组件需要根据 A 计算求出 AA
如果写个普通函数计算,那么每次子组件重新渲染时都会重新计算,比如 B 和 C 改变也会重新计算 A
这时就可以用 useMemo,依赖项写成 A,那么只有 A 改变时才去计算 AA
useCallback
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
可见,useCallback 就是 useMemo 针对函数的特定写法
至于为什么要多此一举设计个 Hook 呢,我猜是官方为了更好的语义