注: 本文是阅读深入 React 技术栈的一些心得, 一部分内容和图片是直接摘抄自此书.
React 组件的生命周期函数是 react 的基础知识, 如果有不熟悉的可以看官方文档. 简单总结如下.
组件的生命周期函数分为两类: 挂载或卸载过程 / 组件更新时. 挂载或卸载过程涉及到三个函数: componentWillMount - 组件即将挂载, componentDidMount - 组件挂载完成, componentWillUnmount - 组件即将卸载. 这些函数都只会在组件初始化或者卸载时运行一次.
组件更新时涉及到四个函数: shouldComponentUpdate - 判断组件是否需要更新, componentWillUpdate - 组件即将更新, componentDidUpdate - 组件完成更新, componentWillReceiveProps - 组件即将接收新的 props.
生命周期整体流程图 - 图片来自于深入 React 技术栈
setState 更是基础的不能再基础的知识了, 用来更新组件的状态. 需要注意的是 setState 是一个异步方法, 一个生命周期内所有的 setState 方法会合并操作.
但是如果把组件的生命周期和 setState 放在一起看就会有一连串的问题: 生命周期函数里可以 setState 吗? 什么时候 setState 合适呢? 阅读完深入 React 技术栈第一和第三章, 得出以下心得:
在 componentWillMount 中执行 setState 是无意义的, 应该将这里的 setState 放到初始化 this.state 的地方去 (如 constructor) 直接作为 state 的初始值.原因是组件只挂载一次, 在 componentWillMount 里 setState 会但是仅会更新 state 一次, 而且会和 constructor 里的初始化 state 合并执行, 因此这是无意义的 setState.
在 componentDidMount 中执行 setState 会导致组件在初始化的时候就触发了更新, 渲染了两遍, 应该尽量避免. 有一些场景, 比如在组件 DOM 渲染完成后获得 DOM 元素位置或者宽高等等设置为 state, 会不得在 componentDidMount 之后 setState, 但是除了这些必要的时候, 都应该尽量避免在 componentDidMount 里 setState.
在 componentWillUnmount 中执行 setState 不会更新 state, 是不生效而且无意义的.
禁止在 shouldComponentUpdate 和 componentWillUpdate 中调用 setState, 这会造成循环调用, 直至耗光浏览器内存后崩溃. 了解了生命周期之后, 这条很好理解. 在 shouldComponentUpdate 或者 componentWillUpdate 里调用 setState 会再次触发这两个函数, 然后在两个函数又触发了 setState, 然后再次触发这两个函数...... 这样就进入了一个不停 setState 然后不停触发组件更新的死循环里, 会导致浏览器内存耗光然后崩溃.[具体分析可以看书的第 3 章]
在 componentDidUpdate 中执行 setState 会导致组件刚刚完成更新, 又要再更新一次, 连续渲染两遍(和在 componentDidMount 中执行 setState 类似). 因此如非必须, 应该尽量避免.
在 componentWillReceiveProps 中可以 setState, 不会造成二次渲染. 由于只有 props 的变化才会触发 componentWillReceiveProps 事件, 因为在这个事件里 setState 不会造成不停触发组件更新的死循环, 可以放心在这个函数里 setState.
生命周期函数里 setState 的时机可以总结为以下表格
来源: https://juejin.im/entry/5af0396351882567236eb022