React生命周期详解

先看图
image.png图片地址

各个阶段生命周期函数

constructor()

官方文档链接
构造函数,在组件被实例化是首先被调用的方法,通常用于完成一下几个任务:

  1. 初始化组件的状态(state):可以在constructor()方法中初始化组件的状态,以便在组件的生命周期中使用他们。
  2. 绑定事件处理函数:可以在constructor()方法中绑定事件处理函数,以便在组件渲染时使用。这样做可以避免组件每次渲染时都重新创建事件处理函数,从而提高性能。
  3. 执行必要的继承操作:如果您想在组件中继承另一个类的属性和方法,可以在 constructor() 方法中调用 super(props) 方法,以确保正确地继承父类的所有属性和方法。例如扩展React.Component。

如果您想要创建一个自定义组件,并且需要访问 React.Component 类中的属性和方法,那么您可以通过继承 React.Component 类来实现。在子类的 constructor() 方法中,需要调用 super(props) 方法,以确保正确地继承 React.Component 类的所有属性和方法。

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    // 初始化组件的状态
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

export default MyComponent;

注意:constructor() 方法中不应该执行与组件状态无关的操作,例如发起网络请求或进行其他副作用。这是因为在 constructor() 方法被调用时,组件的 DOM 节点还没有被创建,因此可能会导致意外的错误。如果在 constructor() 方法中尝试调用 this.setState() 方法,将会引发错误,因为在这个阶段,组件的状态还没有被初始化。

static getDerivedStateFromProps(nextProps, state)

官方文档链接
在调用render方法之前调用。从props中获得state

  • 参数:第一个参数为即将更新的props,第二个参数为上一个状态的state,可以比较propsstate来加一些限制条件,防止无用的state更新。
  • 返回值:返回一个对象来更新state,如果返回null则不更更新任何内容。
  • getDerivedStateFromProps是一个静态函数,不能使用this,也就是只能作一些无副作用的操作。

getDerivedStateFromProps这个函数是用来替代componentWillReceiveProps

componentWillReceiveProps

官方文档链接
在初始化render的时候不会执行,在组件接受到新的props时被触发,一般用于父组件状态更新时子组件的重新渲染。这个方法仅在父组件重新渲染时触发,而不是在内部调用setState时触发。
在这个函数中可以根据this.propsnextprops的变化,通过调用this.setState来更新组件。旧的props可以通过this.props来获取,在这个生命周期函数中更新state是安全的,并不会额外触发render

官网中已经不建议使用个方法。可以使用getDerivedStateFromPropscomponentDidUpdate这两个生命周期函数来替代。
例如:
需要从props中更新state时使用getDerivedStateFromProps生命周期来替代

static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.content !== prevState.arrangedCommandMethod.content) {
    return {
      arrangedCommandMethod: {
        ...prevState.arrangedCommandMethod,
        content: [...(nextProps.content ?? [])],
      }
    };
  }
  return null;
}

需要使用旧的props来做一些事情就用componentDidUpdate

componentDidUpdate(prevProps: PropsType, prevState: StateType) {
  if (prevProps.content !== this.props.content) {
    // .....
  }
}

render()

官方文档链接
render()方法是class组件中唯一必须实现的方法,用于渲染dom。必须要保证render()函数为纯函数,这意味着不能再render里面修改state,否则会触发死循环导致内存崩溃。

componentDidMount()

官方文档链接
componentDidMount()会在组件挂载后(插入 DOM 树中)立即调用,该声明周期是发送网络请求、添加监听事件监听方法的好时机。可以在此声明周期函数中直接调用setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。请谨慎使用该模式,因为它会导致性能问题。
通常,你应该在 constructor() 中初始化 state。如果你的渲染依赖于 DOM 节点的大小或位置,可以使用此声明周期函数。
在该生命周期中setState导致渲染两次的问题,可以使用函数式组件的useEffect来解决
例如:

import { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 发送网络请求获取数据
    const fetchData = async () => {
      const result = await fetch('https://example.com/data');
      const data = await result.json();
      setData(data);
    };
    fetchData();
  }, []); // 第二个参数是一个空数组,表示只在组件挂载时执行一次

  // 在组件中渲染数据
  return (
    <div>
      {data ? (
      <ul>
        {data.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
      </ul>
    ) : (
      <p>Loading...</p>
    )}
    </div>
  );
}

shouldComponentUpdate(nextProps, nextState)

官方文档链接
propsstate发生变化时,会在render()之前调用,默认返回值为true,即重新渲染。首次渲染或者forceUpdate()时不会调用该方法。
常用做性能优化的手段,可以使用内置的PureComponent组件来代替自己重写shouldComponentUpdate()方法。PureComponent默认是浅比较,会比较当前组件的propsstate是否与上一次渲染时的值相同,相同则返回false不更新,否则返回true。
浅比较只会比较对象的引用是否相同,不会递归比较对象的内部属性。如果在propsstate中包含了引用类型的数据,那么默认的浅比较可能就无法满足更新的需求,需要自己重写shouldComponentUpdate()方法,进行深层次比较。
不建议在shouldComponentUpdate()中进行深层次比较或者使用JSON.stringify()。非常影响效率。应该尽量避免使用深层次的 state 结构,因为这样会增加比较的复杂度。
不能在shouldComponentUpdate()中调用setState,会导致死循环。

getSnapshotBeforeUpdate

在最近一次渲染输出(提交到DOM节点)之前调用。它使得组件能在发生变更之前从DOM中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给componentDidUpdate()
此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。
官方给的例子已经很明白了。

componentDidUpdate

会在更新后立即调用。首次渲染不能执行此方法。
包含三个参数,第一个参数是上一次props值,第二个是上一次state值。如果组件实现了getSnapshotBeforeUpdate()生命周期,第三个是该函数的返回值。
可以执行setState(),但是必须把他包裹在一个条件语句里,否则会造成死循环。

componentWillUnmount()

在组件即将被卸载或销毁时进行调用。是清理必要操作的好时机。如,监听事件、清理DOM元素、清理定时器等操作。

注:StrictModel导致渲染两次问题。
image.png
详细官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值