React的生命周期

100 阅读4分钟

1. React是什么?

React是一个由Facebook开发并维护的开源JavaScript库,用于构建用户界面,特别是单页应用程序。在React中,您可以通过组合各种组件来构建复杂的用户界面。

React具有以下几个主要特点:

  1. 组件化:React采用组件化模式,编写的代码具有高度的模块化,可以在不同的场景下复用。

  2. 声明式设计:React采用声明式编程模式,你只需要描述你的组件应该是什么样子的,React会自动确保用户界面与这个描述匹配。

  3. 虚拟DOM:React在内存中维护一个虚拟DOM,当组件状态改变时,React首先会对新的DOM和旧的DOM进行差异比较,然后高效地更新界面,这样就大大提高了应用的性能。

  4. 一次学习,随处编写:React不仅可以开发Web应用,还可以通过React Native开发原生移动应用。

React是一个非常流行的前端框架,它被广泛应用于各种规模的项目,包括许多大型的Web应用。

2. React的生命周期

React组件的生命周期可以分为三个主要阶段:挂载(Mounting)、更新(Updating)和卸载(Unmounting)。在每个阶段,都有特定的生命周期方法可以在特定的时间点被调用。这些方法可以让我们在组件的生命周期中的不同时间点运行代码。

1. 挂载(Mounting)

这是组件实例被创建和插入DOM的阶段,其生命周期方法有:

  • constructor(props): 构造函数,最先被调用,常在这里初始化状态和绑定this。

  • static getDerivedStateFromProps(props, state): 这是一个静态方法,当我们的props引发状态变化时使用,返回一个对象更新状态,或者返回null表示新的props不会引发状态更新。

  • render(): 这个方法是必需的,在这里返回需要渲染的节点内容。

  • componentDidMount(): 组件挂载到DOM后调用,此时可以获取DOM节点并使用,常在此处发起网络请求。

2. 更新(Updating)

当组件的props或state改变时会触发更新。更新阶段的方法有:

  • static getDerivedStateFromProps(props, state): 同上。

  • shouldComponentUpdate(nextProps, nextState): 在组件进行重渲染之前调用,返回false则会停止渲染。

  • render(): 同上。

  • getSnapshotBeforeUpdate(prevProps, prevState): 在最新的渲染输出提交给DOM前将会立刻调用,用于读取最新的DOM数据。

  • componentDidUpdate(prevProps, prevState, snapshot): 在组件更新后立即调用。首次渲染不会执行此方法。

3. 卸载(Unmounting)

这是组件从DOM中移除的阶段:

  • componentWillUnmount(): 在组件卸载及销毁之前直接调用,执行必要的清理操作,如定时器的清理,取消网络请求,清理任何在 componentDidMount() 中创建的订阅等。

以上就是React的生命周期方法,每个方法都有其特定的使用场景和调用时间,理解这些方法的调用时机和使用方法对于编写高质量的React代码非常重要。

需要注意的是,这是React 16.3+版本引入的新的生命周期方法,React团队已经宣布在未来的版本中,一些旧的生命周期方法(如componentWillMountcomponentWillReceivePropscomponentWillUpdate)将会被废弃,因此建议使用上述的新的生命周期方法。

3. 案例

以下是一个简单的React+Redux应用的例子。这个组件会在挂载时从远程服务器获取一些数据,然后更新Redux的状态。这个数据在渲染时从Redux的状态中取得。

首先是Redux的部分。我们有一个简单的Redux状态和action来存储和更新数据:

// actions.js
export const SET_DATA = 'SET_DATA';

export function setData(data) {
  return {
    type: SET_DATA,
    data,
  };
}

// reducer.js
import { SET_DATA } from './actions';

export function dataReducer(state = null, action) {
  switch (action.type) {
    case SET_DATA:
      return action.data;
    default:
      return state;
  }
}

然后是React组件:

import React from 'react';
import { connect } from 'react-redux';
import { setData } from './actions';

class ExampleComponent extends React.Component {
  componentDidMount() {
    fetch('/api/data')
      .then(response => response.json())
      .then(data => this.props.setData(data));
  }

  render() {
    const { data } = this.props;
    return (
      <div>
        {data ? data.map(item => <div key={item.id}>{item.content}</div>) : 'Loading...'}
      </div>
    );
  }
}

// 这里的state是全局的Redux状态
const mapStateToProps = state => ({
  data: state.data,
});

const mapDispatchToProps = dispatch => ({
  setData: data => dispatch(setData(data)),
});

export default connect(mapStateToProps, mapDispatchToProps)(ExampleComponent);

在这个例子中,我们首先定义了一个Redux的action和reducer来处理数据。然后在React组件的componentDidMount生命周期方法中,我们从服务器获取数据,并使用Redux的action来更新数据。

当Redux的状态更新时,React组件会重新渲染,并显示最新的数据。如果数据还在加载,组件将显示"Loading..."。当数据加载完成后,我们使用Redux的setData action来更新状态,然后组件将重新渲染并显示新的数据。

注意,这是一个简化的示例,实际的React和Redux应用可能会涉及更复杂的状态管理和异步操作。