本文中我们同样使用 React 官方教程中的一个时钟的案例来给大家讲解 state 的作用及时生命周期中的一些接口函数。案例可能与官方不是很匹配,是因为我经过刻意修改,为的是以国人理解的方式再重新梳理一遍,让大家更容易理解。

显示一个时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Clock extends Component {
render() {
return (
<div>
<h1>{new Date().toLocaleTimeString()}</h1>
</div>
);
}
}

ReactDOM.render(
<Clock />,
document.getElementById('root')
);

以上代码实现了一个 Clock 的组件,该组件很简单的在一个 h1 标签中显示了当前时间,但是你会发现这个时间是个静止的时间,很明显,它没什么实际作用,我们要想办法让它动起来。所以我们就要用到 state + 生命周期中提供的一些接口来实现这个功能。

使用 state 来显示时钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Clock extends Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}

render() {
return (
<div>
<h1>{this.state.date.toLocaleTimeString()}</h1>
</div>
);
}
}

ReactDOM.render(
<Clock />,
document.getElementById('root')
);

经过改造后,我们仅仅是在构造函数(constructor)中给 this.state 赋了一个初值。然后在 render 中显示了 this.state.date 中的内容。但同样,这个时间还是静止的,我们要想办法让它一秒变一次。那么接下来就用到了生命周期相关的接口。

使用声明周期相关接口

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
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Clock extends Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}

// 组件已经挂载
componentDidMount() {
this.timerId = setInterval(
() => this.tick(),
1000
);
}

// 组件即将被移除
componentWillUnMount() {
clearInterval(this.timerId);
}

// 每一秒设置一次 state 中 date 的值
tick() {
this.setState({
date: new Date()
});
}

render() {
return (
<div>
<h1>{this.state.date.toLocaleTimeString()}</h1>
</div>
);
}
}

ReactDOM.render(
<Clock />,
document.getElementById('root')
);

我们增加了两个函数,一个是 componentDidMount,该函数会在组件已经加载完毕后被调用。另外一个是 componentWillUnMount,该函数会在组件即将被销毁时调用。 我们在 componentDidMount 函数中增加了一个定时器,每一秒调用一次 tick 函数,这个函数是我们新实现的,目的就是调用一下 setState 方法来设置 state 里面的值,当 state 里面的值改变时,控件上使用的 state.date.toLocaleTimeString() 的值也就会跟随变更。这样我们就实现了时间的自动更新。最后在组件即将被销毁时,我们有调用了 clearInterval 清除了定时器。最终时间就会在界面上自动变更了。 这就是 state 的作用,大家可以想一想,如果在传统 web 前端技术中,你想实现这样一个功能要如何实现呢?对比 React 有什么优势或者缺点吗?

注意事项

不可以直接修改状态

1
2
// Wrong
this.state.comment = 'Hello';

必须使用 setState 方法

1
2
// Correct
this.setState({comment: 'Hello'});

你唯一能给其赋初值的地方就是构造函数。

setState 是异步的

参考该文章:https://segmentfault.com/a/1190000007454080