本文中我们同样使用 React 官方教程中的一个时钟的案例来给大家讲解 state 的作用及时生命周期中的一些接口函数。案例可能与官方不是很匹配,是因为我经过刻意修改,为的是以国人理解的方式再重新梳理一遍,让大家更容易理解。
显示一个时间
代码语言:javascript复制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 来显示时钟
代码语言:javascript复制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 中的内容。但同样,这个时间还是静止的,我们要想办法让它一秒变一次。那么接下来就用到了生命周期相关的接口。
使用声明周期相关接口
代码语言:javascript复制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 有什么优势或者缺点吗?
注意事项
不可以直接修改状态
代码语言:javascript复制// Wrong
this.state.comment = 'Hello';
必须使用 setState 方法
代码语言:javascript复制// Correct
this.setState({comment: 'Hello'});
你唯一能给其赋初值的地方就是构造函数。
setState 是异步的
参考该文章:https://segmentfault.com/a/1190000007454080