函数封装的时钟组件
Clock组件需要一个定时器每秒来更新
function Clock(props) {
return (
<h2>{props.date.toLocaleTimeString()}</h2>
)
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root');
)
}
setInterval(tick, 1000);
其实我们希望Clock组件做到自我更新,那么我们就用到了state这个属性,state与props类似,但是state是私有的,完全受控于当前组件。
将函数组件抓换成class组件
1.首先创建一个ES6 class继承于React.Component,然后把函数体放到一个空的render()方法中,注意render()方法中的props替换成this.props,如下:
class Clock extends React.Component {
render() {
return (
<h2>{this.props.date.toLocaleTimeString()}</h2>
)
}
}
2.添加一个class构造函数,在函数中this.state赋初始值,通过super的方式将props传递到父类的构造函数中,然后在render()方法中的this.props.date替换成this.state.date,如下:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date:new Date()};
}
render(){
return (
<h2>{this.state.date.toLocaleTimeString()}</h2>
)
}
}
ReactDOM.render(
<Clock />, //移除date属性
doncument.getElementById('root')
);
3.将生命周期方法添加到Class函数中,实现定时器:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date:new Date()};
}
componentDidMount() { //挂载函数
this.timerID = setInterval(
()=> this.tick(),
1000
);
//把定时器的ID保存在this.timerID
}
componentWillUnmount() { //卸载函数
clearInterval(this.timerID);
}
tick() { //定时器方法
this.setState({ //时刻更新组件的state
date: new Date()
});
}
render() {
return (
<h2>{this.state.date.toLocaleTimeString()}</h2>
)
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root');
);
~注意正确使用state
构造函数是唯一可以给this.state赋值的地方。不要直接修改state,this.state.date = '..'是不会渲染组件的,只有this.setState({date:'..'})才会渲染组件
考虑到性能问题,React可能会把多个setState() 调用合并成一个调用,形成一个异步更新
//这行代码可能无法更新
this.setState({
counter:this.state.counter + this.props.increment
})
//解决这个问题需要在setState()方法里接受一个函数,这个函数用上一个state作为第一个参数,此次更新的props作为第二个参数
this.setState((state, props) => ({
counter: state.counter + props.increment
}))