React 递归重新渲染子组件,但存在一个微妙之处。

原文链接: alexsidorenko.com/blog/react-...

作者:Alex Sidorenko

本篇文章主要聊聊 React 渲染子组件的时候,是否会产生重复渲染的问题,以及为什么会产生这种问题,还有如何规避的一些思考。

我们首先来看一个现象,如果说,这里直接用 Hello,而不用子组件,那么 Resizer 和 Hello 都会被重新渲染。

但如果你传入了 children,这里就智慧重新渲染 resizer。

等一下... React 在状态更新时会递归重新渲染子组件吗?

是的 - 看看这个。然而,重新渲染并不等于 DOM 更新。React 使用协调算法(reconciliation)仅更新 DOM 中所需的最小部分。

那么,为什么 React 不重新渲染 children 属性呢?

React 递归地重新渲染,当它遇到能够保留与上一次渲染相同引用标识的元素时,就可以停止递归。

传递给组件的 props 在组件状态更新时保留其标识。这就是为什么以这种方式组织组件可以作为记忆化的替代方案。

我们可以先来看看,如果不用子组件,直接用 Hello 组件,会有什么效果。

  1. 在重新渲染的时候,会进行比较,看两次是不是相同的
  1. 然后比较 props 的时候,会发现不同,所以需要重新渲染。

那如果是使用子组件的情况呢?

那么会判断它两个是相等的,然后不进行重新渲染。

**但是为什么传递的 props 在重新渲染之间保留标识呢? **

在上面的例子中,children 属性来自 Resizer 的父组件。当我们触发 Resizer 的状态更新时,Resizer 会重新渲染,但其父组件不会。

因此, 元素不会被重新创建,保持了在 Resizer 重新渲染之间的引用标识。请注意,如果更新父组件的状态,所有内容都将重新渲染。

这种优化不仅适用于 children,而且适用于任何 props,比如下面的这个例子。

js 复制代码
// When the state of "Resizer" updates
//"children" and "handle" won't re-render
function Resizer({ children, handle }) {
  let [x, updateX] = useState(0)
  return (
    <div style={{ width: x }}>
      {children}
      <span>{handle}</span>
    </div>
  )
}

我如何在实践中使用它?

这个功能与状态共置技术紧密相连。 通过以一种方式组织组件,将状态与更新此状态的 UI 部分隔离,它自然而然地实现了对 React 应用的优化 在没有使用 refs 和 memo 的情况下优化 React 性能。

不要将本指南作为过分分析重新渲染的理由,因为这是事倍功半的。

编码挑战:LongList 组件在每次鼠标移动时重新渲染,导致性能问题。

你能否通过应用本文中的技术来改善应用的性能?CodeSandbox链接

将包含解决方案的链接作为回复发送给这条推文。

相关文章:

  1. 《在你使用 memo 之前》(作者:Dan Abramov)
  2. 《优化 React 重新渲染的一个简单技巧》(作者:Kent C. Dodds)
  3. 《React 渲染行为的(基本上是)完整指南》(作者:Mark Erikson)
相关推荐
new出一个对象1 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥2 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz5 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript