# 被废弃的生命周期方法

  • componentWillMount()
  • componentWillReceiveProps()
  • componentWillUpdate()

# 废弃的原因

https://zh-hans.reactjs.org/blog/2018/03/27/update-on-async-rendering.html

这些生命周期方法经常被误解和滥用;此外,我们预计,在异步渲染中,它们潜在的误用问题可能更大。 我们将在即将发布的版本中为这些生命周期添加 “UNSAFE_” 前缀。 (这里的 “unsafe” 不是指安全性,而是表示使用这些生命周期的代码在 React 的未来版本中更有可能出现 bug,尤其是在启用异步渲染之后。)

React Fiber 引入了异步渲染,有了异步渲染之后,React组件的渲染过程是分时间片的,不是从头到尾把组件全部渲染完,而是每个时间片渲染一点, 然后每个时间片的间隔都可以去看看有没有更紧急的任务,比如用户的操作,如果有就去处理,如果没有就继续渲染。

React Fiber 架构中,一个组件的渲染分为两个阶段: render阶段 和 commit阶段。

  • “Render 阶段” 纯净且不包含副作用。可能会被 React 暂停,中止或重新启动。 render阶段是可以被打断的,一旦被打断,这阶段所做的事情都被废弃,让React处理完紧急的任务回来,会重新渲染着个组件。 也是就是会执行render()之前的生命周期函数。componentWillMount,componentWillReceiveProps,componentWillUpdate 会被多次调用。

  • “Commit 阶段” 不可被打断,可以使用 DOM,运行副作用,安排更新。

# 废弃的 componentWillMount()

被 componentDidMount 代替

// Before
class ExampleComponent extends React.Component {
  state = {
    externalData: null,
  };

  componentWillMount() {
    this._asyncRequest = loadMyAsyncData().then(
      externalData => {
        this._asyncRequest = null;
        this.setState({externalData});
      }
    );
  }

  componentWillUnmount() {
    if (this._asyncRequest) {
      this._asyncRequest.cancel();
    }
  }

  render() {
    if (this.state.externalData === null) {
      // 渲染加载状态 ...
    } else {
      // 渲染真实 UI ...
    }
  }
}

上述代码对于服务器渲染(不使用外部数据)和即将推出的异步渲染模式(可能多次请求)都存在问题 大多数用例推荐的升级方式是将数据获取移到 componentDidMount:

// After
class ExampleComponent extends React.Component {
  state = {
    externalData: null,
  };

  componentDidMount() {
    this._asyncRequest = loadMyAsyncData().then(
      externalData => {
        this._asyncRequest = null;
        this.setState({externalData});
      }
    );
  }

  componentWillUnmount() {
    if (this._asyncRequest) {
      this._asyncRequest.cancel();
    }
  }

  render() {
    if (this.state.externalData === null) {
      // 渲染加载状态 ...
    } else {
      // 渲染真实 UI ...
    }
  }
}

# 废弃的 componentWillReceiveProps

由于componentWillReceiveProps也会被多次调用,因此避免使用props

  • props 更新state 被 get DerivedStateFromProps 代替
  • props 更新的副作用 被 componentDidMount 代替
  • props 更新时获取外部数据 被 componentDidMount 代替

# componentWillUpdate

# 最佳实践

总之,在Render阶段的生命周期函数不允许有副作用。

副作用只允许在commit阶段的生命周期函数。