什么场景 react 生命周期钩子是必须的

Feeco
  • 9

以下是react生命周期钩子的官方案例,下面这个案例,如果我稍作改动,把setInterval 改成 setTimeout放在render() 里面,这样setTimeout 会setState, 然后循环call render(), 循环setTimeout. 也可以实现,那么这种情况用生命周期钩子为什么是必须的,或者有什么好处呢? 为了代码整洁? 为了减少memory消耗??

原官方案例

 
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  componentDidMount() {
    this.timerID = setInterval(
  this.setState({
      date: new Date()
    }), 1000);
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

我的改动

 
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
 
  render() {
    this.timerID = setTimeout(
    this.setState({
      date: new Date()
    }),1000);
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
回复
阅读 363
3 个回答

你这样如果有其他的state更新,就有多个timeout定时器,即使你在setclear一下,其他的渲染也会重新触发render来导致上一个被清空,所有你的这个方案很简陋,不能拿一个没有应用场景的例子来打败一个官方示例/常用方案

不过单从你这个例子,在前提是整个程序只有这一个组件,整个组件只有一个state,并且没有其他任何东西影响的情况,是可以的,在setTimeout之前clear一下更稳妥一点

标题和问题有点不搭:标题问的是一般情况,问题描述的是一个特殊情况。
先说标题,什么场景 react 生命周期钩子是必须的?至少有两种场景:

  1. 在整个生命周期内只需或必须执行一次的方法,比如要把百度地图渲染到组件中的某一个 canvas 上,由于百度地图初始化的开销会比较大,并且其有着自己的状态,因此多次初始化肯定是不明智的,那么注册一个 componentDidMount 来初始化是再合适不过的了;
  2. 需要依赖生命周期内某个过程才能拿到的信息,还是以百度地图为例,假如需要由父组件参数来修改地图的状态,那么就该注册 componentWillReceivePropsgetDerivedStateFromProps 来监听父组件参数的最新修改,别的地方虽然能拿到参数,但是不会监听参数变化。

很明显,官网例子符合以上第一种情形,注册定时器的代码只需执行一次,后面应该还要注销定时器,注销的代码也只需执行一次。

再来说说你的实现方法,也能用,但是应用面很窄。假如这个定时器不是用来计时的,是用来轮询的,如果轮询结果与上次相同就不重新渲染,也就无法自动注册下一个延时器,那么你就只能借助其他方法来触发一次渲染,属于是不必要的性能浪费。
另外一点,React 始终强调 render 函数应该是纯函数,即给定同样的参数应该得到同样的结果,而延时器其实是有所谓“副作用”的。

小盆友,你这负向优化得妙啊。

你知道吗?

宣传栏