避免React中不必要的渲染
优化你的React前端
[
obed amoasi
[
1 天前-3
](betterprogramming.pub/avoid-unnec…
React的承诺是,当一个组件的道具或状态发生变化时,它将渲染该组件。
虽然这很好,但我们可能不希望所有的变化都能真正触发重新渲染。因此,我们需要很好地处理这些变化。我们将讨论一些情况,在这些情况下我们可以并且应该防止重新渲染的发生。
只传递需要的道具
不要向组件传递不必要的道具,只传递需要的东西。
以2个兄弟组件为例,一个是在屏幕上做动画的圆形组件,另一个是只输出圆形半径的文本组件。
这样做的问题是,尽管Info 不依赖于xCenter 和yCenter ,但当圆在屏幕上移动时,对它的改变将再次被重新渲染,从而导致它重新渲染。
为了解决这个问题,我们应该明确地只把需要的组件传递给子组件。Screen 组件应该被修改成下面这样。
这样,我们可以确保只有需要的道具被传递给组件。这就是我喜欢TypeScript的原因,它可以在不眨眼的情况下标记出初始代码。
使用React.Memo来避免重新渲染
无论如何,即使有了这些改进,我们仍然没有完成。
问题是,如果父组件因为道具或状态的变化而被重新渲染,那么子组件也可能被重新渲染,尽管它并不依赖于道具。
我们可以用记忆化来解决这个问题,这可以确保只有当组件的道具和状态发生变化时才会重新渲染。遵循这个模式,明智地使用React.memo 。
记忆化的组件将看起来像这样。
现在要使用它,我们反而要导入备忘化的版本。而且,我们甚至应该把父类也备忘化,以避免任何重新绘制,这样的话,如果父类的父类发生变化,Screen ,就不会重新绘制。虽然这取决于你的用例,但这可能不会发生。
使用回调来防止多次传递函数
让我们在屏幕上引入另一个组件--一个按钮,它只是坐在那里处理一些点击,做一些非常酷的事情。我们也不要忘了对它进行记忆,这样我们就能得到我们刚才讨论的很酷的功能。
现在,这里有一个问题。用于组件的变化检测是一个浅层的检测,它通常只对参考变化进行比较。
例如,考虑。
const object1 = {a:1}const object2 = {a:1}object1 == object2
这将给你带来错误。这是因为这两个对象指向不同的引用,因此,即使作为道具传递时也是不同的。
<MemoizedButton handleClick={() => {superClick(radius)}}/>
这里发生的情况是,无论何时Screen 组件被渲染,Button仍然会被重新渲染,只是因为一个新的handleClick 将被重新分配。
为了解决这个问题,我们需要把这个函数包在一个useCallback 钩子里。
React官方文档对此有很好的解释。
useCallback将返回一个记忆化的回调版本,只有当其中一个依赖关系发生变化时才会改变。当把回调传递给依赖引用平等的优化子组件时,这很有用,可以防止不必要的渲染
reactjs.org/docs/hooks-…
现在让我们继续讨论列表
始终使用唯一键来避免重新渲染大型列表。没有键是不好的,但是使用一个有可能在渲染筒之间改变的键也是不好的,如果不是 "更坏"。这里的目标是使用一个即使在组件被重新渲染时也不会改变的键。
例如,渲染一个文章卡片的列表,这可以是文章的lug,文章的URL,如果有的话,文章的数据库ID。如果是一个字符串的列表,如果它们是唯一的,字符串本身可以被认为是键。
一旦键是唯一的,React就会知道只渲染列表中变化的项目,而不是在列表中发生变化时渲染整个列表。现在我知道这是一个很大的问题,我将在另一篇文章中进一步解释。
用户资源是很难得的,所以不要使用是不必要的。这是我专注于优化React前端的系列文章的第一部分。谢谢你的阅读。
