React初级学习——6 State&生命周期

一. State:
与props类似,但是是组件内部私有的,完全受控于组件内部的数据。

开始使用state

  1. 首先,创建class组件
class Clock extends React.Component {
  render () {
    return  (
        <div> 
          <h1> Hello </h1>
          <h2> Now, it is {this.state.date.toLocaleTimeString()}</h2>
        </div>      
      );
  }
}
  1. 新建constructor构造函数,在构造函数中添加this.state的初始化赋值
constructor (props) {
  super(props)
  this.state = {date: new Date()};
}

问题:为什么要在constructor第一行进行super(props)调用,详见https://blog.csdn.net/huangpb123/article/details/85009024
完整代码:

class Clock extends React.Component {
  constructor (props) {
    super(props);
    this.state={date:new Date()};
  }
  render() {
    return (
      <div>
        <h1> Hello, world </h1>
        <h2> Now is {this.state.date.toLocaleTimeString()}</h2>
      </div>
    );
  }
}
ReactDOM.render(
  <Clock />,
  document.getElementById("root")
)

这时,我们通过state获取时间,但还不能每1秒进行更新
需要借助生命周期实现周期性更新时间的效果

二. 生命周期

  1. 生命周期方法(类比Vue钩子函数)
    用法:在组件处于某种生命周期状态时,执行某些操作

结合实例需求,需要每秒钟更新this.state.date的值
思路为:
当Clock被“挂载”到真实Dom上时,开启一个计时器,该计时器每一秒更新一次this.state.date的内容;当Clock组件被删除时,再将计时器清除

componentDidMount()函数,则为组件“挂载”阶段
componentWillUnmount()函数,则为组件卸载阶段

故,相应的,在componentDidMount()中,定义开启计时器操作:

componentDidMount() {
  this.timerID = setInterval( //为了方便销毁计时器,需要设置计时器Id
  () => this.tick(),1000
  )
}

在componentWillUnmount()中,则销毁计时器:

componentWillUnmount() {
  clearInterval(this.timerID);
}

最后,我们需要实现在计时器中的tick()方法:
关键函数:必须使用this.setState()方法更新state,因为只有setState()才能让React实现响应式数据效果,即“监测”到state的变化并重新渲染组件(与Vue处理data属性实现数据响应式原理不同)

tick() {
  this.setState({date: newDate()}); //更新‘date’ state
}

总代码:

class Clock extends React.Component {
  constructor (props) {
    super(props);
    this.state={date:new Date()};
  }
  componentDidMount() {
    this.timerID = setInterval(
      ()=> this.tick() , 1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  tick() {
    this.setState({date:new Date()});
  }
  render() {
    return (
      <div>
        <h1> Hello, world </h1>
        <h2> Now is {this.state.date.toLocaleTimeString()}</h2>
      </div>
    );
  }
}
ReactDOM.render(
  <Clock />,
  document.getElementById("root")
)

State的三个注意事项:

  1. 不要直接修改state值,请使用setState(),构造函数是唯一给this.state赋值的地方
  2. state的更新可能是异步(也可以是同步的)的,当需要依赖state和props更新state时,请通过给setState()传入一个函数的方法确保新state的正确性:
this.setState(function(state,props) { //每次的state都是最新的state,即异步调用成功后的state
  return {counter: state.counter+props.increment};
})
  1. State的更新会合并
    对于相同的key的state,只有最后一次的更新生效,即去重
    小难点:如果想基于异步变化的state结果进一步进行操作,需要借助函数式的setState()写法(即第2点中的形式)把每一次的异步结果“连”起来,形成类似“同步”的效果。参考内容:
    https://www.jianshu.com/p/799b8a14ef96

三. 数据流向
数据始终是从父组件流向子组件,父组件中可以通过state,或手写或props来向子组件传递数据,即自组件的props,子组件无从知道数据的具体来源,也无需知道。
有state的组件叫有状态组件,没有的叫无状态组件,可任意穿插使用

推荐阅读更多精彩内容