本文记录个人对React的hook中useEffect,useCallback,useMemo的个人理解。
三者的定义:
useEffect(didUpdate, deps);
const memoizedCallback = useCallback(() => {
doSomething(params);
}, deps);
const memoizedValue = useMemo(() => computeExpensiveValue(params), deps);
三者的第二个deps是一个数组,表示依赖的参数列表,当依赖列表中任一参数变化时,则重新执行前面的函数。如deps = [a,b]
,表示a或者b发生变化则执行前面的函数(注意对象和值的变化方式不同)。
当deps=[]
时,表示只会在组件第一次渲染成功之后执行一次。
useEffect
didUpdate是一个包含命令式、且可能有副作用代码的函数。
didUpdate是组件渲染成功且deps依赖参数发生变化时执行的函数,也就是说useEffect会执行didUpdate
。
didUpdate可以没有返回值,只是执行didUpdate的内容。
didUpdate当它有返回值时,返回值必须是个可执行的函数,目的是用于清除didUpdate执行过程中产生的订阅或者计时器等资源。同时如果didUpdate多次触发,则在每次重新执行前都会先执行返回的可执行函数。(官方称之为清除effect)
如下:
useEffect(() => {
const timer = setInterval(()=>{
console.log('effect')
}, 10*1000);
return () => {
// 清除定时器
clearInterval(timer);
};
});
因此对于useEffect来说,didUpdate时deps有变化时就是执行的,didUpdate若有返回值时,则在下次执行didUpdate时会先执行其返回的函数。
useCallback
返回一个memoized回调函数,我的理解即返回一个函数的句柄,等同于函数的变量,因此你可以使用memoizedCallback()进行执行该函数或者传递给事件和子组件,这里可以推荐绝大多数事件或者子组件的方法使用useCallback,避免组件更新重复渲染。
因此useCallback中的doSomething并不会在定义时就执行,而是需要手动调用返回的memoizedCallback才是真的执行。简单理解为useCallback定义了一个函数,仅在deps发生变化时重新定义该函数,否则该函数的变量不会变化,事件和子组件内容也就不用重新绑定或者渲染。
useMemo
返回一个memoized值,useMemo函数每当deps发生变化时都会调用执行computeExpensiveValue的内容,这是与useCallback最大的不同,useCallback不执行doSomething的内容,只是重新刷新函数句柄。
因此在官方上有这样的一个等式:useCallback(fn, deps)
相当于 useMemo(() => fn, deps)
这应该看懂了吧。deps发生变化时,useCallback返回的是一个可执行fn
的句柄,而useMemo则是执行()=>fn
,但是因为返回的是fn函数,因此当调用这两种时其实执行的是相同的fn
函数内容。
总结
我自身对三者的理解是基于hook定义时:首参是否执行和各自返回内容的作用与差异进行理解,如果本文无法准确描述清楚,建议你也可以从这两方面进行入手分析三者之间的区别和用途。
当然这样的解释和理解可能无法去解释什么情况用useEffect、useCallback、useMemo。但是作为开发者而言,理解hook其定义的差异,亦可理解其不同的用途目的,也就能区分清楚三者各自应在什么情况下进行使用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。