React 的children props渲染问题

组件树的状态对渲染十分重要!!!

jsx 复制代码
const VerySlowComponent = () => {
  console.log("VerySlowComponent render");
  return <div> VerySlowComponent</div>;
};

const ScrollableBlock = ({ children }) => {
  const [count, setCount] = useState(0);
  console.log("ScrollableBlock render");
  return (
    <>
      {count}
      <button onClick={() => setCount((c) => c + 1)}>count++</button>
      {children}
    </>
  );
};

const App = () => {
  return (
    <ScrollableBlock>
      <VerySlowComponent />
    </ScrollableBlock>
  );
};

// 把setCount逻辑移到ScrollableBlock
//count改变,只有ScrollableBlock重新渲染

把setCount逻辑移到ScrollableBlock,count改变,只有ScrollableBlock重新渲染

jsx 复制代码
const VerySlowComponent = () => {
  console.log("VerySlowComponent render");
  return <div> VerySlowComponent</div>;
};

const ScrollableBlock = () => {
  const [count, setCount] = useState(0);
  console.log("ScrollableBlock render");
  return (
    <>
      {count}
      <button onClick={() => setCount((c) => c + 1)}>count++</button>
      <VerySlowComponent />
    </>
  );
};

const App = () => {
  return (
    <ScrollableBlock>
    </ScrollableBlock>
  );
};

这样verySlowCompnent会跟着重新渲染

第一种情况(ScrollableBlock 接收 children 作为 props)

javascript 复制代码
const App = () => {
  return (
    <ScrollableBlock>
      <VerySlowComponent />
    </ScrollableBlock>
  );
};

为什么 VerySlowComponent 不会重新渲染?

  1. children 的稳定性 当 ScrollableBlockchildren 是通过 JSX 直接传递的(如 <VerySlowComponent />),children 的引用在父组件(App)的渲染中始终保持不变。即使 ScrollableBlock 内部状态 count 变化导致自身重新渲染,children 属性(即 VerySlowComponent)的引用未变,因此 React 会跳过子组件的重新渲染
  2. React 的优化机制 React 在对比新旧 props 时,发现 children 的 JSX 元素未发生任何变化(相同类型、相同 props),因此不会触发子组件的重新渲染

第二种情况(VerySlowComponent 直接内嵌在父组件中)

javascript 复制代码
const ScrollableBlock = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      {count}
      <button onClick={() => setCount(c => c + 1)}>count++</button>
      <VerySlowComponent />
    </>
  );
};

为什么 VerySlowComponent 会重新渲染?

  1. 每次渲染生成新的子组件实例 在 ScrollableBlock 的函数体中直接使用 <VerySlowComponent />,每次父组件重新渲染时,都会生成一个新的 VerySlowComponent 实例。React 会认为这是一个新的元素,即使其 props 未变,也会触发重新渲染
  2. children 的引用稳定性保护 此时 VerySlowComponent 是父组件渲染逻辑的一部分,而非通过 children 传递。父组件的任何状态变化都会导致其内部所有 JSX 元素的重新创建,包括子组件

核心差异总结

​​场景​​ ​​子组件接收方式​​ ​​引用稳定性​​ ​​是否重新渲染​​
通过 children 传递 作为父组件的 props 引用不变,React 跳过渲染
直接内嵌在父组件中 父组件渲染逻辑的一部分 每次生成新实例,强制渲染
相关推荐
benbenAItalk8 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
2601_962885728 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
西瓜太郎12348 小时前
Claude Code、Codex CLI、Gemini CLI 能否共用一枚 Key?先看协议选择矩阵
前端·api 网关·claude code·gemini cli·codex cli
陈随易10 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
水域安全老周11 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
计算机魔术师11 小时前
Anthropic CEO突然喊踩刹车,OpenAI罕见力挺:AI这辆车不能只踩油门了
前端
wing9812 小时前
从codex转战workbuddy使用一周的感受
前端·人工智能·后端
EatFan12 小时前
Java接入支付宝 JSAPI 支付保姆教程(二):流程讲解与前后端代码讲解
前端·spring boot·后端·微信小程序·小程序·uni-app
梦想平凡12 小时前
百游棋牌源代码开发搭建教程(五):房间创建、座位分配与请求幂等实现
前端·javascript·数据库·源代码管理
IT_陈寒12 小时前
Redis的Set操作居然能把我的服务整挂了?
前端·人工智能·后端