当前位置: 首页 > news >正文

react state变化生命周期钩子

在 React 中,当组件的 state 发生变化时,会触发一系列方法或生命周期钩子,具体取决于使用的是 类组件 还是 函数组件。以下是详细的触发方法分类:


1. 类组件(Class Component)

state 变化时,类组件会按顺序触发以下方法:

(1) shouldComponentUpdate(nextProps, nextState)

  • 触发时机:在 stateprops 变化后,渲染(render)之前
  • 作用:决定组件是否需要更新(返回 true 则更新,false 则阻止更新)。
  • 注意:如果返回 false,后续的 rendercomponentDidUpdate 不会执行。

(2) render()

  • 触发时机shouldComponentUpdate 返回 true 后。
  • 作用:生成新的 Virtual DOM,准备与旧 DOM 对比。

(3) getSnapshotBeforeUpdate(prevProps, prevState)

  • 触发时机:在 render 之后、DOM 更新之前。
  • 作用:捕获更新前的 DOM 信息(如滚动位置),返回值会传递给 componentDidUpdate

(4) componentDidUpdate(prevProps, prevState, snapshot)

  • 触发时机:DOM 更新完成后。
  • 作用:执行副作用操作(如网络请求、DOM 操作)。

2. 函数组件(Function Component)

函数组件没有生命周期方法,但可以通过 Hooks 监听 state 变化:

(1) 组件重新执行

  • 触发时机state 变化后,整个函数组件会重新执行(包括内部的 useStateuseEffect 等)。

(2) useEffect

  • 触发时机:在组件渲染完成后异步执行。
  • 作用:处理副作用(如数据请求、订阅),依赖 state 时可监听变化。
useEffect(() => {console.log("State changed:", state);
}, [state]); // 依赖 state 变化

(3) useLayoutEffect

  • 触发时机:在 DOM 更新后、浏览器绘制前同步执行。
  • 作用:适用于需要同步更新 DOM 的场景(如测量元素尺寸)。

3. 通用触发机制

无论是类组件还是函数组件,state 变化都会触发以下核心流程:

  1. 状态更新:通过 setStateuseState 的 setter 函数更新 state
  2. 重新渲染:生成新的 Virtual DOM,通过 Diffing 算法找出变化部分。
  3. DOM 更新:仅更新实际变化的 DOM 节点。

4. 特殊情况

setState 回调函数

  • 类组件setState 的第二个参数是回调函数,在状态更新后执行。
this.setState({ count: 1 }, () => {console.log("Updated:", this.state.count);
});

useState 的函数式更新

  • 函数组件:当新状态依赖旧状态时,使用函数式更新避免异步合并问题。
setCount(prevCount => prevCount + 1);

总结对比表

组件类型触发方法
类组件shouldComponentUpdaterendergetSnapshotBeforeUpdatecomponentDidUpdate
函数组件组件重新执行 → useEffect / useLayoutEffect
通用流程Virtual DOM 对比 → 局部 DOM 更新

关键注意事项

  1. 异步更新setStateuseState 的更新是异步的,连续调用可能被合并。
  2. 不可变性:直接修改 state 不会触发更新,必须返回新对象或值。
  3. 性能优化:通过 shouldComponentUpdateReact.memo 避免不必要的渲染。

如果需要更细粒度的控制(如监听特定 state 字段),可以结合 useEffect 的依赖数组或自定义比较逻辑。

旧版本的 React 类组件(Class Component) 中,当 state 发生变化时,会触发一系列生命周期方法。以下是完整的触发顺序和说明:


1. state 变化触发的完整生命周期流程

当调用 this.setState() 或父组件重新渲染导致 state 更新时,会按顺序触发以下方法:

(1) shouldComponentUpdate(nextProps, nextState)

  • 触发时机:在 stateprops 变化后,render 之前
  • 作用:决定组件是否需要更新(返回 true 则继续更新流程,false 则停止)。
  • 示例
    shouldComponentUpdate(nextProps, nextState) {// 只有 count 变化时才更新return this.state.count !== nextState.count;
    }
    

(2) componentWillUpdate(nextProps, nextState)(已废弃 ⚠️)

  • 触发时机shouldComponentUpdate 返回 true 后,render 之前
  • 作用:更新前的准备工作(如记录 DOM 状态)。
  • 注意:React 16.3+ 已废弃,改用 getSnapshotBeforeUpdate

(3) render()

  • 触发时机:生成新的 Virtual DOM,准备与旧 DOM 对比。
  • 规则
    • 必须是纯函数(不能修改 state 或执行副作用)。
    • 返回 React元素数组Fragment

(4) getSnapshotBeforeUpdate(prevProps, prevState)

  • 触发时机:在 render 之后、DOM 更新之前。
  • 作用:捕获更新前的 DOM 信息(如滚动位置),返回值会传递给 componentDidUpdate
  • 示例
    getSnapshotBeforeUpdate(prevProps, prevState) {if (prevState.list.length < this.state.list.length) {return this.listRef.scrollHeight; // 返回滚动高度}return null;
    }
    

(5) componentDidUpdate(prevProps, prevState, snapshot)

  • 触发时机:DOM 更新完成后。
  • 作用
    • 执行副作用(如网络请求、DOM 操作)。
    • 通过 snapshot 获取 getSnapshotBeforeUpdate 的返回值。
  • 示例
    componentDidUpdate(prevProps, prevState, snapshot) {if (snapshot !== null) {this.listRef.scrollTop += this.listRef.scrollHeight - snapshot;}
    }
    

2. 初始化 state 时的生命周期

当组件首次挂载时,会触发以下方法(与 state 变化无关,但涉及初始状态):

  1. constructor() → 初始化 state
  2. componentWillMount()(已废弃 ⚠️)→ 改用 componentDidMount
  3. render()
  4. componentDidMount() → 适合发起异步请求

3. 已废弃的生命周期方法(React 16.3+)

以下方法在 React 16.3 后被标记为不安全,建议避免使用:

  • componentWillUpdate()
  • componentWillReceiveProps()
  • componentWillMount()

替代方案:

  • 使用 getDerivedStateFromProps(静态方法)替代 componentWillReceiveProps
  • 使用 componentDidMount 替代 componentWillMount

4. 完整示例代码

class Counter extends React.Component {constructor(props) {super(props);this.state = { count: 0 };}shouldComponentUpdate(nextProps, nextState) {return this.state.count !== nextState.count;}getSnapshotBeforeUpdate(prevProps, prevState) {console.log("DOM 更新前的快照:", prevState.count);return null;}componentDidUpdate(prevProps, prevState, snapshot) {console.log("DOM 更新完成,当前 count:", this.state.count);}handleClick = () => {this.setState({ count: this.state.count + 1 });};render() {return (<div><p>Count: {this.state.count}</p><button onClick={this.handleClick}>+1</button></div>);}
}

5. 关键注意事项

  1. 异步更新setState 是异步的,连续调用可能被合并(使用函数式更新确保顺序):
    this.setState((prevState) => ({ count: prevState.count + 1 }));
    
  2. 不可变性:直接修改 this.state 不会触发更新,必须返回新对象:
    // 错误 ❌
    this.state.count = 1;
    // 正确 ✅
    this.setState({ count: 1 });
    
  3. 性能优化:在 shouldComponentUpdate 中避免不必要的渲染。

总结(类组件 state 变化流程)

shouldComponentUpdate → render → getSnapshotBeforeUpdate → DOM 更新 → componentDidUpdate

旧版本类组件的生命周期方法提供了精细的控制,但现代 React 推荐使用 函数组件 + Hooks(如 useState + useEffect)替代复杂生命周期逻辑。

http://www.lryc.cn/news/627101.html

相关文章:

  • 【ansible】4.实施任务控制
  • VMware Workstation | 安装Ubuntu20.04.5
  • Linux基础介绍-3——第一阶段
  • 领码方案:通用物联网数据采集低代码集成平台——万物智联时代的黄金钥匙
  • 解决 nginx: [warn] “ssl_stapling“ ignored, issuer certificate not found 报错
  • 计算机视觉 图片处理 在骨架化过程中,每次迭代都会从图像的边缘移除一层像素,直到只剩下单像素宽度的骨架
  • RAG优化进阶 - LinkAI智能体平台的知识库落地实践
  • 数据库架构开发知识库体系
  • 【JavaEE】(17) MyBatis 基础
  • 趣打印高级版--手机打印软件!软件支持多种不同的连接方式,打印神器有这一个就够了!
  • sourcetree 拉取代码
  • HTML--pre标签的作用
  • SpringCloud微服务架构入门指南
  • 8 webUI中-Controlnet(控制与约束)的应用分类与使用方法
  • CentOS 系统 Java 开发测试环境搭建手册
  • 用倒计时软件为考研备考精准导航 复习 模拟考试 日期倒计时都可以用
  • E10 通过RPC实现账号批量锁定与解锁
  • 宝塔部署 Nuxt3
  • 透传 Attributes(详细解析)1
  • 新手向:Python制作简易音乐播放器
  • 软考中级习题与解答——第一章_数据结构与算法基础(1)
  • PyTorch 深度学习常用函数总结
  • Dify 从入门到精通(第 45/100 篇):Dify 的外部系统集成
  • AI 伦理的 “灰色地带”:当算法拥有决策权,公平与隐私该如何平衡?
  • 【C++】模版(初阶)
  • C++ std::optional 深度解析与实践指南
  • kotlin 协程笔记
  • 用Python合成瀑布流图片
  • 【数据类型】
  • python的物资管理系统