React 渲染传导与状态边界
React 中父组件更新如何影响子组件,以及状态上提和状态下沉如何改变渲染边界。
[!info] related notes
React 渲染传导与状态边界
React 性能问题里,真正关键的往往不是某个 Hook,而是“状态放在哪里,会让哪一片组件树跟着重新执行”。
一句话定义
谁持有状态,谁附近的组件树就更可能成为渲染传导的起点;状态放得越高,可能被带动重新执行的范围通常越大。
一个最常见的现象
父组件 state 更新后,父组件会重新执行;如果子组件也在它的渲染树里,子组件通常也会跟着重新执行。
为什么这层比优化 Hook 更重要
因为很多性能问题不是出在:
- 少了一个
useMemo - 没包一个
useCallback
而是出在状态边界一开始就放错了。
如果状态放太高,再多缓存也只是补救,不是根治。
为什么状态边界这么重要
- 状态放得过高,会扩大联动范围
- 状态放得过散,又可能让共享逻辑变乱
- 真正好的设计是让状态尽量靠近真正使用它的地方
一个最典型的判断题
如果一个状态只服务某个局部交互,比如:
- 弹窗开关
- 单个输入框内容
- 某个局部 hover / 展开状态
那通常不要把它放到很高层,否则会扩大 rerender 影响范围。
两种常见调整方向
状态上提
- 共享需求明确时,把状态提升到共同父层
- 解决多个兄弟组件需要共享同一份状态的问题
状态下沉
- 如果某个状态只服务局部交互,就别放在过高层级
- 可以减少无关组件被连带重新执行
一个常见误区
不要把“状态上提”理解成永远更规范。
状态上提是为了解决共享,而不是为了集中一切状态。
如果没有共享需求,过度上提通常只会:
- 放大渲染传播
- 增加 props 透传
- 让组件职责变糊
最短记忆方式
状态放在哪,不只影响代码结构,也影响渲染传导范围。
面试要点
来自 react-parent-child-rerender-interview-question 的面试视角整理。
一句话回答
父组件状态变化后,父组件会重新执行;只要子组件还在它的渲染树中,子组件通常也会跟着重新执行,所以状态放在哪一层会直接影响渲染传导范围。
最稳的回答主线
- 父组件 rerender 时会重新计算它返回的子树
- 子组件因此常会一起重新执行
- 只有当边界设计合理,或优化链路明确时,才值得进一步减少联动范围
一个更完整的面试表达
可以这样答:
父组件状态变化后,父组件会重新执行。因为 React 要重新计算父组件返回的子树,所以子组件通常也会跟着重新执行。
这不代表真实 DOM 一定整棵重建,但函数组件执行链路确实会往下传播。
所以状态放在哪一层,直接决定了渲染影响范围。
一个加分点
如果面试官继续追问,可以补一句:
真正有效的优化经常不是“强行阻止所有子组件 rerender”,而是把状态放在更合理的位置,减少无意义的渲染传播范围。
一个常见误区
很多人一看到父组件带动子组件 rerender,就立刻想上 memo。
但更该先问的是:
- 这个状态是不是放太高了
- 子组件是不是真的很重
- 这次 rerender 到底有没有昂贵工作
最短记忆方式
父组件一刷,子树常常会跟着算一遍。