useMemo
useMemo
用于缓存每次重新渲染都需要计算的结果
语法
useMemo(calculateValue,dependencies)
calculateValue
: 缓存计算值的函数,它应该是一个没有参数的纯函数。React将在首次渲染时调用该函数,在之后的渲染中,如果依赖项(dependencies
)没有发生变化,React将不会调用该函数,而是直接返回缓存的值dependencies
: 依赖项
返回值
- 在初次渲染时,返回
calculateValue
函数的返回值 - 在之后的渲染中,如果依赖项没有变化,则返回缓存的值;如果依赖项发生了变化,将重新调用
calculateValue
函数并计算出新的返回值
用法
useMemo
主要的用法有两种:
- 通过缓存数据,来跳过代价昂贵的计算
- 跳过组件的重新渲染
跳过代价昂贵的计算
例如,我们有一个todos的大数组,需要根据tab来筛选出某些数组项。在初次渲染之后,只有当todos数组或者tab发生改变了才会重新执行过滤数组的方法。
1 | function TodoList({ todos, tab, theme }) { |
跳过组件的重新渲染
例如,ParentComp
组件接受一个theme
的props,用于改变组件内部样式,默认情况下,一个组件重新渲染时,React会递归重新渲染它的所有子组建。也就是,当theme
重新渲染时,会导致SonComp
组件的重新渲染,但其实SonComp
组件并不需要重新渲染。
1 | function ParentComp({ theme }) { |
可以通过将组件用memo
包裹起来,这样当它的props和上次传入的相同时,就不会触发重新渲染
1 | import { memo } from 'react'; |
引出usecallback
现在,SonComp
组件被包裹在memo
中,接收一个函数作为props。每次ParentComp
组件重新渲染,都会导致handleClick
函数的重新创建,即产生不同的handleClick
,这就会导致SonComp
组件的重新渲染
1 | function ParentComp({ theme }) { |
我们很容易想到使用useMemo
来缓存handleClick函数,如下所示:
1 | const handleClick = useMeme(() => { |
这样看上去就很冗余了,在React中有另外一个Hook用于缓存函数。
useCallback
useCallback
允许你在多次渲染中缓存函数
语法
useCallback(fn, dependencies)
fn
: 想要缓存函数,它可以传入任何参数并且返回任何值。React将在首次渲染时返回(不是调用)该函数,在之后的渲染中,如果依赖项(dependencies
)没有发生变化,React将返回相同的函数。在任何渲染中,React都不会调用该函数,而是返回该函数dependencies
: 依赖项
返回值
在初次渲染时,useCallback
返回你已经传入的fn
函数
在之后的渲染中, 如果依赖没有改变,useCallback
返回上一次渲染中缓存的fn
函数;否则返回这一次渲染传入的fn
。
用法
接着上面的例子对handleClick
进行改造,使它也被缓存起来
1 | const handleClick = useCallback((args) => { //和普通函数一样使用 |