博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为何要在componentDidMount里面发送请求?
阅读量:6909 次
发布时间:2019-06-27

本文共 2452 字,大约阅读时间需要 8 分钟。

转自

在我们编写React代码的时候,总会遇到这么一个问题:请求接口并展示我们获取到的数据。这听起来很简单,但是你有没有想过一个问题:在何时进行进行网络请求才是最好的?我相信你们都会说,我当然知道,在 componentDidMount 中啊,因为这是React官方推荐的,不服上个图

这一下你应该服了吧?服是服了,但为什么是 componentDidMountconstructorcomponentWillMount不可以吗?

首先我们来百度一下,这是一个最高赞的答案

总结一下:

  1. componentDidmount 是在组件完全挂载后才会执行,在此方法中调用setState 会触发重新渲染,最重要的是,这是官方推荐的!

  2. constructor 调用是在一开始,组件未挂载,所以不能用。

  3. componentWillMount 调用在 constructor 后,在这里的代码调用 setState 不会出发重新渲染,所以不用。

  4. 还有一个没有出现在这里但听得最多的说法是:在 componentWillMount 里进行网络请求会阻碍组件的渲染。

  5. 反正就是要在 componentDidmount 里用!

说的好像挺有道理的,但是也感觉怪怪的,看的再多不如自己动手测试一下。首先测试一下 constructor

constructor

class Parent extends React.Component {  constructor(props) {    super(props);
this.state = {  text: 'plain text'};fetch('https://s.codepen.io')  .then(res => this.setState({text: 'success'}))  .catch(err => this.setState({text: 'error'}))复制代码

}

render() { return ( <div> <h1>{this.state.text}</h1> </div> ); } }

复制代码

ReactDOM.render( <Parent/>, document.getElementById('root') ); 复制代码复制代码

戳看演示,state从一开始的plain text变成了error(因为跨域问题,请求无法成功,但是没有关系)

所以上面说的constructor 调用时组件未挂载,所以不能用的说法是错误的,组件未挂载也可以发送请求,这里所影响的时间只有执行发送请求的时间,然后组件接着渲染,等异步数据返回后,再执行 setState,或许你会说,如果请求时间很短,在组件挂载之前就返回了怎么办,此时的 setState 还会起作用吗?别着急,这个问题后面会提到。

componentWillMount

将请求移到 componentWillMount

class Parent extends React.Component {  constructor(props) {    super(props);
this.state = {  text: 'plain text'};复制代码

}

componentWillMount() { fetch('') .then(res => this.setState({

text: 'success'})) .catch(err => this.setState({
text: 'error'})) }

render() { return ( <div> <h1>{this.state.text}</h1> </div> ); } }

ReactDOM.render( <Parent/>, document.getElementById('root') );

复制代码

复制代码复制代码

戳,可以看到,state也是从plain text 变成了error,嫌太快看不清楚的可以用setTimeout模拟一下。这就很奇怪了,不是说willMount里面setState不会重新渲染吗?不是说网络请求会阻塞组件的渲染吗?然而都没有,其实原理跟constructor是一样的,所影响的时间只有执行发送请求的时间,并不会阻塞组件的渲染,但不推荐使用 componentWillMount 是有其他的原因:

  1. 很重要的一点,React16.3后将会废弃掉componentWillMount、componentWillReceiveProps 以及 componentWillUpdate 三个周期函数,直到React 17前还可以使用,不过会有一个警告。

  2. 跟服务端渲染有关系(同构),如果在 componentWillMount 里获取数据,fetch data会执行两次,一次在服务端一次在客户端,使用 componentWillMount 则没有这个问题。

至于前面说到的数据在组件挂载前返回导致不生效的,这种情况并不会发生, 因为 setState 是将更新的状态放进了组件的__pendingStateQueue队列中,react并不会立即响应更新,会等到组件挂载完成后,再统一更新脏组件,见下图

因此,从另外的角度看,放在constructor或者componentWillMount里面反而会更加有效率。

总结

  1. 数据获取可以放在 constructor 或者 componentDidmount 中,不建议放在 componentWillMount。 但是为了更好的代码规范和可读性,建议统一放在 componentDidmount

  2. 对于首次render没有数据,可能导致出错的。可以设置一个initial state,或者增加一个loading状态,加载数据时展示一个spinner或者骨架图都是比较常用的方案。

参考链接

转载地址:http://xlfcl.baihongyu.com/

你可能感兴趣的文章
2的倍数相加后如何还原
查看>>
W3C 、HTML 、CSS 发展介绍
查看>>
JS实现点击跳转登陆邮箱
查看>>
Alexandra and Prime Numbers(思维)
查看>>
jQuery hover 延时器实现代码
查看>>
ArcGIS JS 学习笔记3 实现百度风格的BubblePopup
查看>>
JavaScript之字符串引号的使用技巧
查看>>
linux如何关闭selinux?
查看>>
初识CSS
查看>>
Android开发常用代码片段
查看>>
微信小程序使用场景及取名“潜”规则
查看>>
Atitit nodejs5 nodejs6 nodejs 7.2.1 新特性attialx总结
查看>>
回顾 git 常用命令
查看>>
第四章 Spring.Net 如何管理您的类___统一资源访问接口
查看>>
最大流+最小费用最大流
查看>>
java-mybaits-00103-入门程序原生的【查、增、删、改】
查看>>
LayoutInflater
查看>>
用sourceTree提交代码时遇到的问题
查看>>
Mysql第一周
查看>>
深入理解 Android 消息机制原理
查看>>