https://reactjs.org/docs/state-and-lifecycle.html
在关于state中,教程中先把之前章节中提到的例子clock
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);
先从外观上封装起来,使用组件的形式<Clock/>
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
从html组织结构上看,已经将clock封装成了一个组件了,但是更新组件ui的功能却独立于组件之外,因此还是可以继续改进的,组件应该自己负责它要实现功能的执行逻辑,比如clock组件应该是当提供给别人使用使用时候,自动管理更新界面的功能,如同我买了一个表,装上电池后他自己走动,而不是作为一个使用者还要一遍遍的拨动他的轮盘让他走动.
而要实现组件内的逻辑处理,就需要使用state这个新东西了,而且state只能用在class形式的组件形式,不能用于函数式组件,state和prop很像,只是他可以更改.
class形式的组件比函数式组件多出的功能: state,生命周期钩子函数
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
this.props是react自己设置,this.state也有特殊的意义, 如果你要设置的变量用于存储状态,而这些值不需要与UI关联,那你可以直接在this上绑定新的变量,比如 this.a=1
class Clock extends React.Component {
constructor(props) { //构造函数 每次渲染组件都会调用,必须带props属性用于接收来自组件外的属性
super(props);
this.state = {date: new Date()}; //初始化state的值
}
componentDidMount() { //当组件被渲染到DOM上的时候被调用
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() { //组件从dom中移除的时候调用
clearInterval(this.timerID);
}
tick() {
this.setState({ // 如果state有多个key ,这样 只是更新对应的key而不是覆盖,是一种合并merge的操作,类似 {...ob}的操作
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
不要直接操作state, 应该使用setState({}),而且这种方式是异步的,可能要在下一次js循环中才能修改,需要注意不要依赖this.state计算下次的值
// Wrong 无法保障state一定是最新的
this.setState({
counter: this.state.counter + this.props.increment,
});
// Correct 传递一个回调函数,在下一次js循环中被调用
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
有关state的使用, 应该做到父组件和子组件都不关心彼此的数据来源与使用情况,相互独立,例如可以通过父组件传递他的this.state中的值给子组件,变成子组件的prop,子组件访问这个prop就可以了 组件间是彼此隔离的,数据从上而下传递,像瀑布一样,上面组件的数据只可能影响到子组件而不会对上层组件产生影响.