一文搞懂React中props导致的更新 #120
zhangyu1818
announced in
zh-cn
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
最近去了新公司,发现有的同事还是准规守矩的写着
useCallback
、useMemo
,让随意的我很头大。本文内容只限于函数组件,本文中的“更新”指代的是函数组件重新执行。
下面就简单的谈一谈,组件究竟在什么情况下会更新。
正文之前
在探究原理之前,需要先简单的了解几个知识点。
组件究竟是因为什么更新?
这有一个简单的例子。
<Child>
组件没有接收state
的值,每次点击<div>
让state
更新,<Child>
组件会更新吗?...
...
...
答案是会更新的,有些小伙伴可能会好奇,为什么子组件没有接收任何的
props
,为什么也会更新呢?组件更新的先决条件
oldFiber.memoizedProps
即是目前的props
。newFiber.penderProps
即是即将更新的props
,它被赋值为了JSX对象的props
。beginWork
阶段,经判断props
不相同。这里就是新旧
props
最初对比的地方,在React中当前组件的对比仅用了!==
来判断,每次生成JSX对象时,即使为空,也会生成不同的props
空对象。有什么方法可以避免这种无效更新呢?
避免组件更新的3种方式
React.memo
,它可以像类组件的PureComponent
一样在对比的时候做第一层的浅对比,具体原理可以看我之前的文章React中Props的浅对比。这种方式可以理解为父级将
<Child>
作为props
传入了当前组件。推荐React团队成员Dan的一篇文章在你写memo()之前。
何时使用useCallback和useMemo?
考虑以下情况,经过
React.memo
的<Child>
组件在state
改变后会更新吗?...
...
...
答案是会更新的。
因为函数组件更新实际会重新执行一次该函数本身,所以内部的函数也会重新生成,即便函数内容相同,但不是同一个函数,在
React.memo
浅对比时也不相同。解决这种问题的方法即是使用
useCallback
。由
useCallback
将每次函数执行产生的内部函数返回为同一个函数,这样在React.memo
的时候浅对比就相同了。其实还有一种方式来固定函数。
可能会比较奇怪,但是
useRef
其实可以做到更好的固定效果。useCallback和useMemo是最优解吗?
可能会有小伙伴和我同事一样的想法,不管三七二十一,总之全包上就行,总不会出错了吧~
其实并不是这样,我们在使用
useCallback
和useMemo
的时候其实都会有额外的消耗。这是
useCallback
的源码截取,实际上我们在使用它的时,最多会产生两个函数,和两个依赖数组,同时还会有依赖数组的遍历比较。所以使用它们并不一定会起到性能优化的效果。
我觉得适用的场景
useCallback
如果子组件一定会更新,那么固定函数的意义就不大了。
当每次更新时
state
都会改变,那么固定函数也是徒劳的。useMemo
props
相同。state
值的对象缓存后传递给子组件,不会让子组件更新。useMemo
缓存计算结果。结语
滥用
useCallback
和useMemo
可能不会起到性能优化的情况,还是需要酌情考虑,过早的优化也不一定是正确的。React里面的水太深,小张也把握不住,如果文中有错误,还望大佬们指出讨论。
Beta Was this translation helpful? Give feedback.
All reactions