状态 state 和生命周期

state 状态

props 是父级传给子组件的数据,state 是组件自己的数据管理,在这里我们叫状态。

不使用 hook 的情况下,函数组件自己没有 state 状态和生命周期,所以,这篇的状态和生命周期是围绕 class 组件开展的。

示例:

// 一般state我们写在第一个生命周期函数里constructor里
constructor() {
  this.state = {
    data: {},
    str: '数据'
  }
}
// 也可以省去constructor
state = {}
1
2
3
4
5
6
7
8
9

需要注意一点,在 constructor 里的都需要加 this,如果有 constructor 那么 state 必须要写在里面。

class 语法里 construtor 是构造函数,是 class 被实例化时自定执行的第一个函数。所以在 class 组件里也是生命周期的第一个初始化阶段。es6-calss 语法·阮一峰open in new window

修改状态

在 react 里修改 state 不能直接修改,需要使用 setSate 方法
this.setState 类组件专属方法

this.setState({
  data: newData,
});
1
2
3

常规的修改状态上面的写法足矣,但是 setState 方法是一个异步方法,所以我们没有办法在修改后获取最新的值,所以 setState 还有另一种写法。

this.setState(
  (state) => {
    state.data = "newData";
  },
  () => {
    console.log(this.state.data, "这里可以拿到修改后的新值");
  }
);
console.log(this.state.data, "这里拿不到修改后的新值");
1
2
3
4
5
6
7
8
9

生命周期

  1. constructor 初始化生命周期
  2. render 解析(渲染)dom 生命周期
  3. componentDidMount 完成挂载
  4. componentDidUpdate 完成更新
  5. componentWillUnmount 准备卸载

一些即将在 v17 版本被废弃的生命周期

  1. componentWillMount 准备挂载
  2. componentWillUpdate 准备更新

constructor

只会执行一次,初始化生命周期

// 由于类组件是继承的React.Component
// 所以必须super初始化一下
constructor() {
  // super函数必须是在顶端声明,这样才能拿到自己的this
  super()
  // 一般这里存放状态
  this.state = {}
  // 在构造函数里的都要加this
}
1
2
3
4
5
6
7
8
9

render

初始化执行一次,props 和 state 更新时会执行

我本人更认为 render 是解析 jsx 的函数,真正的渲染函数其实是 ReactDOM.render 方法。

需要注意一点,就是 render 里的 jsx 必须要放在一个根元素里

render() {
  // 可以用占位标签包裹,并且不会渲染出dom节点
  return <>****</>
}
1
2
3
4

<></>其实是React.fragment

componentDidMount

完成挂载生命周期,只会执行一次。

一般用来写完成页面呈现后,加载接口数据,或监听事件等。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: [],
    };
  }

  componentDidMount() {
    fetch("https://api.example.com/items")
      .then((res) => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items,
          });
        },
        // 注意:需要在此处处理错误
        // 而不是使用 catch() 去捕获错误
        // 因为使用 catch 去捕获异常会掩盖掉组件本身可能产生的 bug
        (error) => {
          this.setState({
            isLoaded: true,
            error,
          });
        }
      );
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map((item) => (
            <li key={item.name}>
              {item.name} {item.price}
            </li>
          ))}
        </ul>
      );
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

componentDidUpdate

完成更新生命周期,只在 props 更新和 state 更新时执行

componentWillUnmount

准备卸载的生命周期,只会在组件被销毁时执行,一般用来做用户离开时提醒,或组件被销毁时注销全局对象等操作。

componentWillMount

即将在 v17 版本被抛弃的准备挂载生命周

componentWillUpdate

即将在 v17 版本被抛弃的准备更新生命周

强制更新方法

this.forceUpdate() 需要注意的是,一旦使用,它将破坏性能优化里的方法:shouldComponentUpdate 和 PureComponent

Last Updated:
Contributors: websong