【发布时间】:2018-02-13 02:12:31
【问题描述】:
在 componentWillMount 生命周期方法中触发服务器调用以获取数据是一种不好的做法吗?
以及为什么使用 componentDidMount 更好。
【问题讨论】:
标签: javascript reactjs redux react-redux
在 componentWillMount 生命周期方法中触发服务器调用以获取数据是一种不好的做法吗?
以及为什么使用 componentDidMount 更好。
【问题讨论】:
标签: javascript reactjs redux react-redux
更新: componentWillMount 很快就会成为deprecated。
在未来的 React 版本中,我们预计 componentWillMount 在某些情况下会触发不止一次,因此您应该使用 componentDidMount 来处理网络请求。
阅读更多here。
【讨论】:
按照我的理解,最大的原因之一与为开发人员设置正确的期望阅读代码有关。
如果我们使用componentWillMount,很容易认为获取有时间发生,然后组件“确实”挂载,然后第一次渲染将会发生。但事实并非如此。如果我们进行异步调用(如使用 Promises 的 API 调用),组件将实际运行 render,然后 fetch 可以返回并设置组件状态(或更改 Redux 状态,或其他任何方式)。
如果我们改为使用componentDidMount,那么很明显该组件将在您取回任何数据之前至少呈现一次(因为该组件已经进行挂载)。因此,通过扩展,很明显我们必须以某种方式处理初始状态,以便组件不会在第一次(“空”)渲染时中断。
【讨论】:
componentDidMount 是调用获取数据的最佳位置,原因有两个:
使用componentDidMount 可以清楚地表明,在初始渲染之前不会加载数据。您需要正确设置初始状态,以免获得导致错误的undefined 状态。
如果您需要在服务器上呈现您的应用程序,componentWillMount 将被调用两次(在服务器上和客户端上),这可能不是您想要的。将数据加载代码放入componentDidMount 将确保仅从客户端获取数据。一般来说,你不应该给componentWillMount添加副作用。
【讨论】:
更新 - 2018 年 5 月
在名为 async rendering 的工作进程中有一个新的 react 功能。
从 react v16.3.2 开始,这些方法使用起来并不“安全”:
您可以在docs 中阅读更多相关信息。
作为一般规则 don't use componentWillMount (如果您使用 es6 class 语法)。请改用constructor 方法。
这种生命周期方法适用于同步状态初始化。
另一方面,componentDidMount 适用于异步状态操作。
为什么?
好吧,当您在 constructor / componentWillMount 中执行异步请求时,您会在调用 render 之前执行此操作,当异步操作完成时,render 方法很可能已经完成并且没有必要设置这个阶段的“初始状态”是什么?
我不确定这是否是您的情况,但开发人员希望在componentWillMount 中异步启动状态的大多数情况是为了避免第二次render 调用。但是你不能避免它,就像上面提到的那样,render 无论如何都会在异步操作完成之前触发。
因此,调用异步操作的最佳时间是在调用 render 并安装组件之后(您可以安装 null 或空的 <div/>),然后获取数据,设置状态并使其重新分别渲染。
【讨论】:
setState 这样的反应代码)都是同步的。所以是的,我们的代码将在异步代码之前运行完成。当然,除非我们使用异步 API,例如 setTimeout promise 等。
组件挂载生命周期是
Constructor 和 componentWillMount 都在负责页面渲染的 render() 调用之前调用。
这里的状态初始化是在构造函数中完成的,并且由于异步调用而在 componentDidMount 中调用了 api。
ComponentWillMount 在 ES6 之前的初始化状态很好,当构造函数不存在时。但是现在 ComponentWillMount 没什么用,react 团队在 react 17 之后才考虑它。
除上述之外,react 已移至 reactfiber architecture,为避免不必要的重新渲染并提高性能,react 已决定放弃 componentWillMount、componentWillReciveProps 和 componentWillUpdate 方法。
【讨论】: