很多人不使用这俩,因为搞不清楚
useCallback
和 useMemo 的实际作用,先说说这俩是做什么的。
简介 useCallback
与 useMemo
1. useCallback
useCallback
主要作用,是为了优化渲染性能,避免过度渲染而存在的。当一个函数依赖某些状态,去做一些事情。但是当这些状态并没有变更的时候,就可以使用 useCallback
来避免重新创建函数。最好是在依赖项比较多活着依赖项是函数的时候使用。
const memoizedCallback = useCallback(()=>{
doSomething(a, b);
}, [a, b])
2. useMemo
useMemo
的主要作用是为了缓存计算的结果,避免重复计算。有点像 vue
中的 computed
。当某个值需要变化的值来计算生成时,而且这个值又会在多个地方使用的时候,就应该想到 useMemo
来缓存了。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
这里说几个注意的点
-
怎么写全依赖项
建议可以使用
ESLint
的插件eslint-plugin-react-hooks
检测。 -
对于依赖项
建议使用具体的值,而不是函数作为依赖项。
因为函数作为依赖项,还是会导致不必要的渲染。😭
-
不建议使用
useCallback
的时候- 同步执行的函数,不建议使用
useCallback
, 因为没有必要缓存const memoizedCallback = useCallback(() => { doSomething(a, b); },[a, b]);
- 异步执行的函数,建议配合
useEffect
一起使用const MyComponent = ({ id }) => { const [data, setData] = useState(null); const fetchData = useCallback(async () => { const result = await fetch(`/api/data/${id}`); const data = await result.json(); setData(data); }, [id]); useEffect(() => { fetchData(); }, [fetchData]) return {data}; });
- 同步执行的函数,不建议使用
说点其他的
过渡渲染
在
react
应用中,由于组件的状态或者属性的变化,引起组件频繁的重新渲染的情况。 当组件重新渲染时,react
会重新生成新的虚拟DOM
树,并将其与旧的虚拟DOM
数进行比较,从而确定需要更新哪些部分的实际DOM
。这个过程消耗很大。
解决这种过度消耗的方式,上面讲的两种就在其中。
使用回调函数,可以降组件变化的依赖项直接传递给回调函数,而不是直接在组件中处理。故而,依赖的项先计算影响 DOM
渲染的数据,数据不变,不需要重新渲染。
除去上面说的两种之外, React.memo
, React.PureComponent
, shouldComponentUpdate
也可以优化过去渲染。