# 被废弃的生命周期方法
- 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阶段的生命周期函数。