You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React调和过程中组件是否必重渲染?相关实现疑问咨询

React渲染与调和过程解析及疑问解答

示例代码

import React from "react";

export default function App() {

  console.log("App is rerendered")

  const [time, setTime] = React.useState(0)

  React.useEffect(() => {
    const lol = setTimeout(() => setTime(prev => prev + 1), 100)
    return () => clearTimeout(lol)
  }, [time]
  )

  function ShowTime() {
    console.log("ShowTime is rerended")
    return (
      <div> Time : {time / 10} sec</div>
    )
  }

  function ShowButton() {
    console.log("ShowButton is rerended")
    return (
      <button
        onClick={() => console.log("I'm hard to click cuz rerendered the whole time :/")}>
        Button created with ShowButton component
      </button>
    )
  }

  return (
    <main>
      <ShowTime />

      <ShowButton />

    </main>
  )
}

我对代码执行过程的理解

  • React创建包含App元素、ShowTime元素和ShowButton元素的虚拟DOM
  • 首次渲染时,React渲染所有内容,创建App实例,其包含一个main DOM元素,以及ShowTime和ShowButton的实例
  • 100ms后,App中的time状态发生变化
  • React结合time状态的变化再次更新虚拟DOM
  • 触发重渲染,进入调和阶段

基于React文档的理解

当组件更新时,实例保持不变(...)。接下来,会调用render()方法(...)

  • React不会纠结App本身有没有变化,只要在虚拟DOM中遇到组件,提交阶段就会保留实例并执行App.render(),这里因为time状态变化,这个行为是合理的
  • 对子组件执行递归调和过程
  • 同理,React也不会纠结ShowTime和ShowButton有没有变化,只要是组件就保留实例,执行它们的render()方法

我的疑问

  • 我对调和过程中组件相关逻辑的理解是否正确?
  • 当父组件需要渲染时,无论子组件是否关联到props或状态变化,都会被渲染吗?比如示例中的ShowButton组件,这导致按钮难以点击,是否合理?

解答

关于调和过程的理解是否正确?

你的理解大体方向是对的,但有个关键细节需要修正:
因为ShowTime和ShowButton是定义在App组件内部的函数组件,每次App重渲染时,这两个函数都会被重新创建,相当于全新的组件类型(函数引用发生了变化)。这时候React不会保留旧的子组件实例,而是直接销毁旧实例、创建新实例,这也是它们每次都会打印"rerended"的核心原因之一。

除此之外的逻辑是正确的:父组件状态变化触发重渲染后,会进入调和阶段,类型匹配的组件实例会被保留,并重新执行渲染逻辑生成新的虚拟DOM,再递归处理子组件。

父组件渲染时子组件一定会跟着渲染吗?这种情况合理吗?

默认情况下是的,父组件重渲染时,所有直接或间接子组件都会跟着重渲染,不管子组件有没有用到变化的状态或props。

示例里ShowButton难以点击完全不合理,这是代码写法导致的问题:App每100ms就重渲染一次,加上ShowButton是内部定义的组件,每次都会被重新创建,对应的DOM元素也会频繁销毁重建,按钮一直在刷新自然很难被点击。

解决这个问题可以这么做:

  1. 把ShowTime和ShowButton移到App组件外部定义,这样它们的函数引用不会每次变化,React会识别出是同一个组件,ShowButton没有依赖任何props,只会渲染一次。
  2. 用React.memo包裹ShowButton,让React对比前后props,没有变化就跳过重渲染(更推荐第一种方案)。
  3. 优化定时器逻辑:把useEffect的依赖改成空数组,用setInterval代替嵌套的setTimeout,减少不必要的重渲染次数。

内容的提问来源于stack exchange,提问作者Fabien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:06:24