减少子组件重复渲染:
getDerivedStateFromProps
当父组件重新渲染,不论传入当前组件的props是否发生变化,其getDerivedStateFromProps都会被执行,这将导致不必要的重复渲染。
当组件setState执行后,其getDerivedStateFromProps也都会被执行。
组件的getDerivedStateFromProps方法应用于组件state仅根据传入props变更进行更新的场景。
对于表单,通过使表单控件成为完全受控组件,props和onChange由父组件传入,子组件不维护state,或使表单控件成为完全不受控组件,只从父组件获取初始props,子组件通过setState维护state,通过变更子组件key重置state,两种方式可以避免getDerivedStateFromProps。
shouldComponentUpdate
在上面情形中,当getDerivedStateFromProps被执行后,会继续React组件生命周期,故shouldComponentUpdate也都会被执行。
通过shouldComponentUpdate对新老props(或新老state)进行比对,判断是否发生变化,返回比对结果,可以避免由此造成的子组件重复渲染。
PureComponent
React在PureComponent组件中封装了通过shouldComponentUpdate进行新老props和(或新老state)比对的更新策略,当父组件更新与当前组件无关时,则不会触发当前组件更新,并跳过当前组件的整个子组件树(故子组件也应是PureComponent或静态组件)。
需要注意的是,PureComponent组件仅仅是通过shouldComponentUpdate对props和state进行了浅比较,对于props或state数据的层级不是扁平结构时将不会对更深层级数据变化进行比对。
如果state和prosp不可避免使用深层数据,可以通过使用不可变对象提升深层数据比较速度。
对于state深层更新,还可以通过更新时直接对深层数据使用新对象来触发组件渲染。
如果能够确切知道某些深层数据发生变化,则可以调用component.forceUpdate方法跳过比较直接进行强制更新。
memo
对于函数组件,可以使用React.memo方法对组件进行封装,React.memo本身是一个HOC,传入函数组件和更新判断方法,实现类似类组件中shouldComponentUpdate方法的功能,更新判断方法为可选参数,为空时默认对props进行浅比较,否则按照更新判断方法进行数据比对。
与PureComponent不同的是React.memo仅对props进行比对,不比对state。
与shouldComponentUpdate不同的是React.memo的更新判断方法返回true时为不更新,而shouldComponentUpdate则相反。
需要注意的是,React.memo应作为性能优化手段而不是渲染控制逻辑来使用。
setState机制:
当调用组件setState方法后,React会进行虚拟DOM更新、合成更新、diff算法比对,经过以下四个生命周期:
- getDerivedStateFromProps
- shouleComponentUpdate
- render
- componentDidUpdate
由React触发的setState每次执行时都会进行合成更新,因此由React绑定的事件处理函数(如onClick、onChange等)、生命周期函数中调用setState,都时异步执行的;不经过React控制、直接触发(如原生DOM绑定的事件处理函数、setTimeout/setInterval、Promise回调函数等)的setState会同步执行。
由于setState的异步执行机制,当多次调用setState方法时,应传入更新回调方法进行更新,而不是直接使用this.state值ÿ