以下内容原文来自:https://facebook.github.io/react/docs/state-and-lifecycle.html
Start:
State and Lifecycle
01,想一下之前的 ticking clock 例子;到目前为止,我们只学习了跟新UI界面的一种方法-->
-----> 我们调用React.render() 方法去改变渲染出来的界面;
------>
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组件,它可以设定自己的时间,而且可以每秒钟自己更新时间
我们暂时将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);
但是这样写忽略了一个关键需求:设置时间和每秒钟更新时间,应该是Clock组件本身来实现的细节
理想中,我们希望写的像下面的代码,同时可以实现Clock组件自己更新时间;
ReactDOM.render( <Clock />,//clock组价 document.getElementById('root') );
为了能够实现这个,我们需要在Clock组件中添加 state 状态;
state 和 props 类似,但是它是私有的,完全被组件所控制;
我们之前提到过,定义为Class 的组件有一些附加的特性 --> local state 只能用于 class;
Converting a Function to a Class /将function定义的组件转换为class定义
1.用es6 class name extends React.Component
2.添加 redder 方法
3.将原先function 中的函数体 放到 render 方法中
4. 用this.props 替换props
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } }
Adding Local State to a Class/添加状态
1. 用this.state.date替换this.props.data
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
2.添加构造函数 并制定 this.state
class Clock extends React.Component {
constructor(props) {//构造函数 注意这里传了 props **##Class components should always call the base constructor with props
.
super(props);
this.state = {date: new Date()};//状态
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
3. 将date prop 从Clock组件中删除
ReactDOM.render( <Clock />, document.getElementById('root') );
到此为止 代码如下
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> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
接下来,让clock组件自己跟新
Adding Lifecycle Methods to a Class/添加生命周期方法
在拥有很多组件的应用中,当组件销毁时,释放组件所占的资源很重要;
每当clock 组件第一次渲染时,我们就设置一个计时器 ,----> mounting
每当clock 组件移除时,我们就清空计时器 -----> unmounting
--->声明生命周期函数方法
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() {//已经渲染到dom this.timerID = setInterval(// () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ 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') );
-->关系<--
1.<Clock/>组件传递到 ReactDom.render() 后,React 调取Constructor,组件需要显示当前时间->
this.state将会被更新
2.React 调用 组件的render()方法,将组件跟新到Dom;
3.组件更新到Dom后,React 调用componentDidMount()钩子-->组件通知浏览器设置timer
4.每次调用tick()方法,组件会调setState()方法,React知道state改变以后重新调用render()方法
5. 假如组件从Dom中移除,React 调用componentWillUnmoint() 停止timer
Using State Correctly/正确使用State
1.不要直接修改state
// Wrong this.state.comment = 'Hello'; // Instead, use setState(): Correct this.setState({comment: 'Hello'});
2.state 的更新可能是异步的,不能依赖它们的值,正确的做法是
setState()接收一个函数,函数接收previous state 作为参数
// Wrong this code may fail to update the counter: this.setState({ counter: this.state.counter + this.props.increment, }); // Correct this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));