关于react.js:React-18生命周期

63次阅读

共计 7053 个字符,预计需要花费 18 分钟才能阅读完成。

  • 原文地址 – 全栈小册:https://skillgroup.cn/framework/react/life-cycle.html

React 生命周期流程图

React 生命周期线上地址

React.Component 构造函数

1. 目标

构造函数在 React 组件的生命周期中十分晚期被调用,它产生在组件实例被创立并插入到 DOM 之前。这使得它成为初始化组件的本地状态和绑定事件处理函数的现实地位。

2. 应用

如果您的组件不须要初始化状态或绑定事件处理函数,那么您不须要显式地定义一个构造函数。然而,如果您的确这样做了,那么在构造函数的第一行调用 super(props) 是必要的。

3. 为什么要调用 super(props)

在 JavaScript 类中,子类的构造函数必须在应用 this 之前调用 super。在 React 组件中,super 援用的是 React.Component 的构造函数。调用 super(props) 确保您能够在构造函数中应用this.props

4. 初始化状态

构造函数是为 this.state 设置初始值的中央。这是通过间接为 this.state 调配一个对象来实现的。例如:

this.state = {counter: 0};

请留神,您不应该在构造函数中调用setState()

5. 绑定事件处理函数

为了确保事件处理函数中的 this 援用的是组件实例,您须要在构造函数中绑定它。例如:

this.handleClick = this.handleClick.bind(this);

6. 防止的做法

  • 不要在构造函数中调用 setState():这是因为this.state 能够间接在构造函数中进行初始化。
  • 防止引入副作用或订阅 :构造函数不是执行网络申请、设置订阅或手动更改 DOM 的中央。这些都应该在componentDidMount() 或其余生命周期办法中进行。
  • 防止将 props 间接复制到 state:这是因为当 props 更改时,state 不会自动更新,可能导致组件的渲染状态与 props 不同步。

7. 示例代码

class MyComponent extends React.Component {constructor(props) {super(props);
    this.state = {counter: 0};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {// 事件处理逻辑}

  // ... 其余办法和渲染逻辑
}

8. 不应用构造函数的代替办法

constructor在 React 组件中是能够省略的。然而,是否省略取决于您的组件须要执行哪些初始化操作。以下是一些状况阐明:

不须要初始化状态,也不须要绑定办法

如果您的组件不须要初始化本地状态,并且您也不须要绑定任何办法到组件实例,那么您能够齐全省略constructor

应用类属性

在古代的 React 版本中,您能够应用类属性来初始化状态,而不须要显式的constructor。例如:

class MyComponent extends React.Component {state = { counter: 0};
  // ... 其余代码
}
应用箭头函数主动绑定办法

如果您应用箭头函数定义方法,那么这些办法会主动绑定到以后实例,因而不须要在 constructor 中进行绑定。例如:

class MyComponent extends React.Component {handleClick = () => {// 事件处理逻辑};
  // ... 其余代码
}

综上所述,如果您应用类属性和箭头函数,那么在许多状况下,您都能够省略constructor。然而,如果您须要执行更简单的初始化逻辑,或者须要在创立组件实例时执行某些操作,那么依然须要constructor

getDerivedStateFromProps

在 React 的世界里,组件的属性(props)和状态(state)是外围概念。有时,咱们须要依据属性的变动来更新状态。这就是 getDerivedStateFromProps 办法的舞台。

什么是getDerivedStateFromProps

getDerivedStateFromProps是 React 组件的一个动态生命周期办法。它容许咱们在组件接管新的属性时更新状态。这个办法在组件的挂载和更新阶段都会被调用。

执行机会

1. 挂载阶段(Mounting)

当组件实例被创立并插入到 DOM 中时,getDerivedStateFromProps会在 render 办法之前被调用。这容许您依据组件的初始属性来设置组件的初始状态。

2. 更新阶段(Updating)

当组件接管到新的属性或状态更改时,getDerivedStateFromProps也会被调用。具体来说,它会在以下状况下被调用:

  • 当组件接管到新的属性时(即父组件从新渲染)。
  • 当您调用 setState 办法更新组件的状态时。
  • 当您调用 forceUpdate 办法强制从新渲染组件时。

在这些状况下,getDerivedStateFromProps都会在 render 办法之前被调用,容许您依据新的属性或状态来更新组件的状态。

参数解释

  • nextProps:组件行将接管的新属性。
  • prevState:组件以后的状态。

返回值

  • 返回一个对象来更新状态。
  • 如果不须要更新状态,则返回 null。

利用场景

  1. 属性派生状态 :当组件的外部状态须要从属性派生时。
    假如您有一个主题组件,它的色彩能够通过属性来管制,但也能够由用户在组件外部更改。
class ThemeComponent extends React.Component {state = { color: this.props.color};

  static getDerivedStateFromProps(nextProps, prevState) {if (nextProps.color !== prevState.color) {return { color: nextProps.color};
    }
    return null;
  }

  render() {return <div style={{ backgroundColor: this.state.color}}> 主题色彩 </div>;
  }
}
  1. 条件渲染 :依据属性管制组件的渲染。
    假如一个权限管制组件可能会依据传入的权限级别显示或暗藏某些性能。
class PermissionComponent extends React.Component {state = { isAdmin: this.props.isAdmin};

  static getDerivedStateFromProps(nextProps, prevState) {if (nextProps.isAdmin !== prevState.isAdmin) {return { isAdmin: nextProps.isAdmin};
    }
    return null;
  }

  render() {return this.state.isAdmin ? <AdminFeatures /> : <UserFeatures />;}
}

注意事项

  • getDerivedStateFromProps 是一个静态方法,因而它不能拜访组件实例的 this。这意味着您不能在此办法中调用组件的实例办法或拜访组件的实例属性。
  • 因为 getDerivedStateFromProps 在多个阶段都可能被调用,因而您可能须要增加额定的逻辑来确定何时应该更新状态。
  • getDerivedStateFromProps 应该是一个纯函数,不要在其中执行有副作用的操作,如网络申请或订阅事件。

shouldComponentUpdate

1. 根本用法

shouldComponentUpdate 是一个可选的生命周期办法,用于在接管新的 props 或 state 时确定组件是否应该从新渲染。它返回一个布尔值,通知 React 是否应持续更新过程。

shouldComponentUpdate(nextProps, nextState) {
  // 逻辑判断
  return true 或 false;
}

2. 性能优化

a. 防止不必要的渲染

如果您的组件常常接管雷同的 props 或 state,但不须要每次都从新渲染,那么 shouldComponentUpdate 就派上用场了。

shouldComponentUpdate(nextProps, nextState) {return nextProps.value !== this.props.value;}

b. 自定义比拟逻辑

您能够依据须要编写自定义的比拟逻辑,只有在满足特定条件时才从新渲染。

3. 与 PureComponent 的关系

React.PureComponent 通过浅比拟 props 和 state 来主动实现 shouldComponentUpdate。如果您的组件继承自 PureComponent,则不须要手动实现此办法。

4. 执行机会

1. 接管新的 Props 或 State

当组件接管到新的 props 或 state 时,shouldComponentUpdate 将被调用。这是一个决策点,让您能够判断是否真的须要从新渲染组件。

2. 父组件从新渲染

当父组件从新渲染时,子组件的 shouldComponentUpdate 也会被调用。这样,您能够管制子组件是否随父组件一起从新渲染。

3. 应用 forceUpdate

如果您调用了组件的 forceUpdate 办法,shouldComponentUpdate 将被跳过,组件将强制从新渲染。

4. 初始化渲染

值得注意的是,shouldComponentUpdate 不会在组件的初始化渲染阶段被调用。它仅在组件的更新阶段起作用。

5. 注意事项和最佳实际

a. 防止副作用

shouldComponentUpdate 只利用于渲染决策,不应执行任何副作用,如网络申请或批改全局变量。

b. 防止深度比拟

深度比拟可能会耗费大量性能,反而升高利用的响应速度。

c. 不要在此办法中调用 setState

这会导致组件从新渲染,从而引发有限循环。

getSnapshotBeforeUpdate

1. 什么是 getSnapshotBeforeUpdate

getSnapshotBeforeUpdate 是 React 的一个生命周期办法,用于在 DOM 更新之前捕捉一些信息。这个办法在最新的渲染输入被提交到 DOM 之前被调用,容许您在更新产生之前捕捉一些对于 DOM 的信息。

2. 办法签名

getSnapshotBeforeUpdate(prevProps, prevState);
  • prevProps: 更新前的属性。
  • prevState: 更新前的状态。

3. 返回值

这个办法应返回一个值,该值将作为 componentDidUpdate 的第三个参数。如果您不须要捕捉任何信息,能够返回 null

4. 应用场景

a. 捕捉滚动地位

如果您的组件波及到滚动,并且在更新后须要放弃滚动地位,能够应用以下代码:

getSnapshotBeforeUpdate() {return this.containerElement.scrollTop;}

componentDidUpdate(prevProps, prevState, snapshot) {this.containerElement.scrollTop = snapshot;}

b. 捕捉表单状态

如果您的组件蕴含表单,并且您想在更新之前捕捉表单的状态,能够这样做:

getSnapshotBeforeUpdate() {return this.formElement.values;}

componentDidUpdate(prevProps, prevState, snapshot) {// 应用捕捉的表单状态}

c. 比拟属性和状态

您还能够应用这个办法来比拟前后属性和状态的变动,从而执行一些特定的逻辑。

5. 注意事项

  • getSnapshotBeforeUpdate 必须与 componentDidUpdate 配合应用。
  • 不要在这个办法中触发状态更新,否则会导致有限循环。

componentDidMount

在 React 18 中,componentDidMount 依然是一个重要的生命周期办法,但随着 React Hooks 的风行,许多开发人员可能会转向应用 useEffect 钩子来代替。不过,对于那些仍在应用类组件的我的项目,componentDidMount 依然是一个弱小的工具。

1. 数据获取

componentDidMount 是一个现实的中央来执行异步操作,例如从 API 获取数据。这样做能够确保组件曾经挂载到 DOM 中,因而您能够平安地更新状态。

componentDidMount() {fetch('/api/data')
    .then(response => response.json())
    .then(data => this.setState({ data}));
}

2. 增加事件监听器

如果您须要在组件挂载后增加事件监听器,componentDidMount 是一个完满的中央。

componentDidMount() {window.addEventListener('resize', this.handleResize);
}

3. 操作 DOM

如果您须要间接操作 DOM,componentDidMount 能够确保 DOM 曾经筹备好。

componentDidMount() {this.myInput.focus();
}

4. 执行机会

componentDidMount 是一个生命周期办法,它会在组件第一次渲染到 DOM 之后立刻调用。这意味着它是在组件的第一次渲染实现后执行的,但在任何子组件的 componentDidMount 之前执行。

上面是执行机会的具体解释:

  • 组件挂载实现:当组件被插入到 DOM 中后,componentDidMount 将被调用。此时,您能够平安地执行波及 DOM 的操作。
  • 仅执行一次:与其余生命周期办法不同,componentDidMount 只在组件挂载后执行一次。如果您须要在组件更新后执行某些操作,您可能须要应用 componentDidUpdate
  • 在子组件的 componentDidMount 之前执行:如果有子组件,父组件的 componentDidMount 将在任何子组件的 componentDidMount 之前执行。
  • render 办法之后执行componentDidMount 是在 render 办法之后执行的,所以在 componentDidMount 中调用 setState 将触发额定的渲染,但这不会让用户看到中间状态。

哎呀,你齐全对了!我居然忘了提到 componentDidUpdate 的执行机会,这可是理解它的要害局部。让我补充一下:

componentDidUpdate 执行机会

1. 组件更新后

componentDidUpdate 的名字曾经暗示了它的执行机会:组件更新后。然而,什么会导致组件更新呢?

  • 属性变动:当组件接管到新的属性时,它会触发更新。
  • 状态变动:当组件的状态扭转时,它也会触发更新。
  • 父组件从新渲染:即便属性和状态没有扭转,父组件的从新渲染也会导致子组件更新。

2. 不会在初始渲染时执行

当组件首次挂载时,componentDidUpdate 是不会被调用的。如果你须要在首次渲染后执行某些操作,能够应用 componentDidMount 办法。

3. render 办法之后

componentDidUpdate 是在 render 办法之后执行的,所以你能够确信此时 DOM 曾经更新。这使得 componentDidUpdate 成为执行与 DOM 相干操作的现实机会。

4. getSnapshotBeforeUpdate 之后

如果你应用了 getSnapshotBeforeUpdate 办法,那么 componentDidUpdate 会在它之后执行。这样你能够在 getSnapshotBeforeUpdate 中捕捉一些信息,并在 componentDidUpdate 中应用。

5. 根底用法

componentDidUpdate 的根底用法非常简单。它接管三个参数:

componentDidUpdate(prevProps, prevState, snapshot) {// ...}
  • prevProps:前一个属性对象。
  • prevState:前一个状态对象。
  • snapshot:从 getSnapshotBeforeUpdate 办法返回的值。

componentWillUnmount

1. 什么是 componentWillUnmount

在 React 中,当一个组件不再须要时,componentWillUnmount 办法会被调用。这是一个清理组件相干资源的好时机。

2. componentWillUnmount 的用法

清理定时器

如果组件中设置了定时器,当组件卸载时,定时器应该被革除,以防止不必要的谬误和资源节约。

componentWillUnmount() {clearInterval(this.timerID);
}

勾销网络申请

如果组件中发动了网络申请,当组件卸载时,应该勾销未实现的申请,以防止不必要的正告和潜在的谬误。

componentWillUnmount() {this.source.cancel('组件卸载,勾销申请');
}

移除事件监听器

如果组件中增加了事件监听器,当组件卸载时,应该移除这些监听器,以防止内存透露。

componentWillUnmount() {window.removeEventListener('resize', this.handleResize);
}

正文完
 0