React无疑是目前最流行的前端View库之一。在业务开发中,开发者经常会因为网络请求时间点的选择而纠结,那么这篇文章一定会给你带来一些帮助。
本文所提到的网络请求主要是组件初始化请求,不包括触发式请求(比如点赞请求、评论请求等)。
首先我们需要明确的是可进行网络请求的React类组件生命周期:1
2
3
4constructor()
componentWillMount()
render()
componentDidMount()
React在官方文档中提到,componentDidMount是比较适合进行网络请求的地方:
大多数情况下,在didMount中进行网络请求确实比较稳妥,不太容易出现问题。但在实际开发中,可能会由于需求的不同而存在更多的请求节点选择。
同步网络请求
同步的请求很少出现。这类请求最好在constructor和willMount阶段进行,因为同步请求会阻塞React组件的渲染及浏览器事件。
在组件渲染完毕,会调用didMount方法。如果在这个时间发送同步请求,务必会阻塞用户和页面的交互,造成页面假死的现象。
而在render之前,constructor和willMount均未渲染出页面,此时进行同步请求也只会使用户觉得组件或页面正在加载中。异步网络请求
异步网络请求是在开发中最常见的,它并不会阻塞组件的渲染。将这类请求放在constructor和willMount中效率会更高。
异步请求在取得response后通常会使用setState来触发render。didMount调用时实际上已经render过一次,如果在didMount中请求数据,至少会经历两次render(假设请求成功)。
setState实际上是将更新的状态放进了组件的__pendingStateQueue队列。
速度足够快的情况下,在constructor和willMount中的请求能够在第一次render前进行setState,此时setState并不会触发渲染,而是会在组件进行第一次render的时候统一渲染,实际只进行了一次render。
如果没有在第一次render前获取到response,最多也只会和didMount中请求一样的效果,进行两次渲染。
综上,将异步请求放在constructor和willMount中会显得更加的高效。在construcor中发出的异步请求(microTask)如果足够快,会在组件没有mounted前调用setState,这个时候是不成功的,必须直接使用this.state = {} 的形式设置state,这需要增加额外的判断。
不涉及UI渲染的网络请求
我们一般不依赖这类请求的response,只需要强调请求的发送。所以比较适合在constructor阶段完成。SSR(服务端渲染)
如果网站考虑SSR的话,那么网络请求要尽可能的放到didMount中,因为didMount在SSR的过程中并不会被执行,且SSR生成HTML的过程中也不需要执行网络请求(没有意义)。Fiber reconciler
Fiber是React16所采用的协调算法,可以通过这篇文章深入了解。
使用Fiber后,组件render前的生命周期方法可能会被打断,也就意味这这些方法可能会被多次执行。因此,在React16后,初始网络请求都要尽量在didMount中执行。
总结


