一文搞懂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
Uh oh!
There was an error while loading. Please reload this page.
-
最近去了新公司,发现有的同事还是准规守矩的写着
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