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

React如何识别已更新组件?状态变更触发重渲染机制解析

React 是如何识别组件内部状态变更并触发重渲染的

测试代码

import React from 'react';

const App = () => {
  console.log('app render');

  return (
    <div>
      <Children />
    </div>
  );
};

const Children = () => {
  const [update, setUpdate] = React.useState(false);

  console.log('children render');

  return (
    <div>
      <button onClick={() => setUpdate(!update)}>update</button>
    </div>
  );
};

export default App;

代码运行表现

代码首次加载完成时,控制台会按顺序打印app render、children render两条日志;点击页面上的update按钮后,控制台只会输出children render,外层的App组件不会触发重渲染。

具体原理

入门时学到的三类React组件重渲染触发规则是准确的:

  • 组件接收的props发生变化
  • 组件自身维护的state发生更新
  • 父组件触发重渲染时,未做memo优化的子组件会默认连带重渲染

你提到的props变更感知逻辑是对的:父组件执行render的过程中,React会比对子组件前后接收的props是否变化,以此判断要不要更新子组件。但组件内部state的识别逻辑和props完全不一样:useState返回的setter方法(也就是示例里的setUpdate)本身就是React提供的,调用它的动作就是在主动告知React当前组件需要更新,不存在React主动"探测"state变化的过程。

React从来没有做变量层面的劫持、代理来监听普通变量的变化,整个state触发更新的链路非常直白:

  1. 组件首次渲染调用useState时,React会在当前组件对应的内部Fiber节点(React用来存储组件状态、组件树关系的核心数据结构)上,存好初始state值和对应的setter函数。
  2. 你在事件回调里调用setter、传入新的state值时,setter会直接把新值更新到对应Fiber节点的状态存储位,同时直接给这个Fiber节点打上「待更新」标记,启动React的更新调度流程。
  3. 调度流程启动后,React只会从标记为待更新的节点开始,向下遍历子树执行渲染逻辑,不会向上遍历父组件节点——这就是示例里点击按钮后只有Children组件重渲染、父组件App完全不触发render的根本原因。

补充:如果你在组件里声明普通let/var变量,哪怕手动修改了它的值,因为没有调用React提供的setter方法,React收不到任何更新通知,根本不会触发重渲染,这也是普通变量不能替代state做响应式数据的核心原因。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 06:12:22