React6—— react生命周期(新) + 例子

本文详细介绍了React的新生命周期,包括初始化阶段、挂载阶段、更新阶段和卸载阶段的关键方法,如getDerivedStateFromProps、shouldComponentUpdate、getSnapshotBeforeUpdate和componentDidUpdate。并强调了这些方法在不同阶段的作用,如componentDidMount用于执行异步操作,getDerivedStateFromProps用于根据props更新state,以及在组件卸载时进行必要的清理操作以防止内存泄漏。同时,提醒开发者注意生命周期函数的使用规则和避免死循环的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生命周期 (新)

在这里插入图片描述

初始化阶段
  • constructor()

类的默认方法,在类中是必须存在的,里边的super()方法是必须的,如果没有定义constructor(),会默认生成一个空的构造器constructor

挂载阶段

(componentWillMount() ->) render() -> componentDidMount()

componentWillMount() ❌:组件挂载之前调用,很少使用, 17.0 版本将会删除)

  • render():是组件中必须定义的,用来渲染DOM,并必须 return 一个React元素(描述组件,即UI)

  • componentDidMount(): 组件完成后调用 ,componentDidMount在渲染过程中永远只有执行一次,一般是在componentDidMount执行副作用,进行异步操作,并在异步请求中可以进行setState;也可以在这里使用refs,获取真实dom元素。

更新阶段

但凡stateprops发生更新,不管是否改变,都会引起子组件重新render

static getDerivedStateFromProps(nextProps, prevState) -> shouldComponentUpdate(nextProps,nextState) -> getSnapshotBeforeUpdate(prevProps, prevState) -> componentDidUpdate(prevProps, prevState)

  • static getDerivedStateFromProps(nextProps, prevState)v16.4新增加的生命周期
    • nextProps表示更新后的 props,prevState表示更新前的 state
    • 根据nextPropsprevState计算出预期的状态改变,返回结果会被送给setState,也就是说我们可以根据propsstate的变化情况来决定返回情况
    • ⚠️这个生命周期函数是一个静态函数,因此是无法访问实例的属性和方法的(就不能使用this
    • 返回值如果是object,就相当于是setState操作;如果是null或者其他基本类型,就不会更新state没有返回值会报错
    • 这是一个例子🌰:
static getDerivedStateFromProps(nextProps, state) {
  const param = nextProps.search.substring(1)
  if (param !== state.param) {
    return {
      param,
      loading: true
    }
  }
  return null;	
};

(componentWillReceiveProps(nextProps )❌17.0 版本将会删除)

  • shouldComponentUpdate(nextProps,nextState)
    • 通过比较nextPropsnextState及当前组件的this.propsthis.state的状态用来判断是否需要重新渲染
    • 默认返回true,需要重新render,返回false则不触发渲染。
    • 可以用来优化组件性能
  • getSnapshotBeforeUpdate(prevProps, prevState)v16.4新增加的生命周期
    • 作用是在真实 DOM 更新(componentDidUpdate)前,获取一些需要的信息(类似快照功能),然后作为参数传给 componentDidUpdate
    • prevProps表示更新前的 props,prevState表示更新前的 state
    • 返回值是一个快照(Snapshot),如果返回null就表示不生成快照,若有有效返回值,返回值会作为componentDidUpdate(prevProps, prevState)第三个参数
    • ⚠️这个生命周期函数必须和componentDidUpdate(prevProps, prevState)同时使用,否则报错
    • 这是一个例子🌰:
getSnapshotBeforeUpdate() {
    // 返回更新内容的高度 300px
    return this.wrapper.current.scrollHeight;
  }
componentDidUpdate(prevProps, prevState, prevScrollHeight) {
    this.wrapper.current.scrollTop =
      this.wrapper.current.scrollTop +
      (this.wrapper.current.scrollHeight - prevScrollHeight);
  }

(componentWillUpdate(nextProps,nextState)❌17.0 版本将会删除)

  • componentDidUpdate(prevProps, prevState)

    • 可以操作组件更新的DOM,prevPropsprevState这两个参数指的是组件更新前的propsstate
    • 这个函数内要谨慎的使用setState,使用该钩子内setState有可能会触发重复渲染,需要自行判断,否则会进入死循环。下图就是无条件使用setState时产生的错误:
      在这里插入图片描述
      componentDidMount 里面 setState 导致组件更新,组件更新后会执行 componentDidUpdate,此时你又在componentDidUpdate 里面 setState又会导致组件更新,造成成死循环了
卸载阶段
  • componentWillUnmount()

组件卸载前调用,经常用来执行一些清理操作,比如清理定时器,取消订阅等等来避免内存泄漏。

注意⚠️
  • 新的生命周期函数不可以🚫和即将废弃的两个函数同时使用
  • getDerivedStateFromProps并不是只会在 props “改变”时才会调用。实际上只要父组件重新渲染时,这个生命周期函数就会重新调用,不管 props 有没有“变化”

下面是一个例子🌰:

import React, { Component } from 'react'

export default class LifeCycle extends Component {
     props = {age:10,name:'计数器'}
  static defaultProps = {
      name:'计数器'
  }
  constructor(props){
      //Must call super constructor in derived class before accessing 'this' or returning from derived constructor
    super();//this.props = props;
    this.state = {number:0,users:[]};//初始化默认的状态对象
    console.log('1. constructor 初始化 props and state');

  }  
  //componentDidMount在渲染过程中永远只有执行一次
  //一般是在componentDidMount执行副作用,进行异步操作
  componentDidMount(){
    console.log('3. componentDidMount 组件挂载完成');
    fetch('https://api.github.com/users').then(res=>res.json()).then(users=>{
        console.log(users);
        this.setState({users});
    });
  }
  shouldComponentUpdate(nextProps,nextState){
    console.log('Counter',nextProps,nextState);
    console.log('4. shouldComponentUpdate 询问组件是否需要更新');
    return true;
  }
  componentDidUpdate(prevProps, prevState)){
    console.log('5. componentDidUpdate 组件更新完毕');
  }
  add = ()=>{
      this.setState({number:this.state.number});
  };
  render() {
    console.log('2.render渲染,也就是挂载')
    return (

      <div style={{border:'5px solid red',padding:'5px'}}>
        <p>{this.props.name}:{this.state.number}</p>
        <button onClick={this.add}>+</button>
        <ul>
            {
                this.state.users.map(user=>(<li>{user.login}</li>))
            }
        </ul>
        {this.state.number%2==0&&<SubCounter number={this.state.number}/>}
      </div>

    )
  }
}
### React 组件生命周期方法使用指南 #### 类组件的生命周期方法 React 的类组件拥有多个生命周期方法,这些方法允许开发人员在特定的时间点执行代码。例如,在组件挂载之前、之后或是更前后都可以触发相应的生命周期回调。 - **componentDidMount**: 当组件已经加载到 DOM 中时调用此方法。通常用来发起网络请求获取数据或设置定时器等操作[^1]。 ```javascript class MyComponent extends React.Component { componentDidMount() { console.log('Component has been mounted'); } } ``` - **shouldComponentUpdate(nextProps, nextState)**: 返回布尔值决定是否重渲染组件。如果返回 `false` 则不会继续后续流程;反之则会进入下一个阶段并最终完成重绘. ```javascript shouldComponentUpdate(nextProps, nextState) { return this.state.count !== nextState.count; } ``` - **UNSAFE_componentWillMount** 和其他不推荐使用的生命周期方法:某些早期版本中存在的生命周期函数现在被认为是不安全的,并将在未来的版本中被移除。比如 `UNSAFE_componentWillMount()` 就是一个例子,应当避免在其的应用程序里使用这类方法[^3]。 - **componentWillReceiveProps(nextProps)**: 如果父级传递给子组件的属性发生变化,则会触发这个方法。需要注意的是即使 props 没有实际变化,只要父组件重渲染就会引起该事件的发生[^4]. ```javascript componentWillReceiveProps(nextProps) { if (this.props.id !== nextProps.id) { // handle prop change... } } ``` 随着 Hooks API 的推出,许多传统意义上的生命周期概念已经被简化或者替代了。对于现代应用来说,更倾向于采用基于 Hook 的方式来管理状态和副作用。 #### 函数组件中的钩子(Hooks) 自 React 版本 16.8 开始引入了 Hooks 功能,这使得我们可以更加灵活地编写可复用逻辑而无需依赖复杂的高阶组件模式或者是 Render Props 技术。通过像 useState 或 useEffect 这样的内置 hook ,可以轻松实现原本只有 class 才能拥有的能力——即声明式的定义响应式行为以及副作用控制[^2]。 - **useState**: 提供了一种简单的方式来跟踪 UI 上的状态变量。每当 state 发生变更都会自动触发视图刷过程。 ```javascript import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); function incrementCounter() { setCount(count + 1); } return ( <> <p>Current count is {count}</p> <button onClick={incrementCounter}>Increment</button> </> ); } ``` - **useEffect**: 它类似于之前的 `componentDidMount`, `componentDidUpdate` 和 `componentWillUnmount`. 此外还可以指定依赖项列表以便仅当那些值发生更改时才运行效果代码片段。 ```javascript import { useEffect } from 'react'; function Example() { useEffect(() => { document.title = `You clicked ${count} times`; // 清理工作会在卸载前被执行 return () => {}; }, [count]); // 只有当 count 改变才会再次执行 effect } ``` 综上所述,虽然传统的类组件仍然支持完整的生命周期机制,但对于建项目而言建议尽可能多地利用 hooks 来构建功能模块,因为这种方式不仅简洁明了而且更容易维护和发展下去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值