【性能优化】降低re-render

1. 前置说明

1.1 React的思维模式

view = fn(props, state, context)

  • 只要参数发生改变,视图一定发生re-render
  • 没有被子组件使用的props会被丢弃,比如传递了style,但是子组件没有操作style属性,或者没有restProps,则style无效

1.2 React的变更

默认是指【指针的变更】,不会监听对象的属性变更

  • 采用Object.is(valA, valB)进行比较
  • useState产生的值,需要setState()会触发re-render,和上一次一致时,不触发re-render
  • 可以采用immutability-helper对复杂对象进行处理
    对象变化
  • 可以采用useMemo,监听变量未改变,则产生的值也不会变

1.3 React父组件re-render的影响

若父组件发生了re-render,则子组件也会re-render

  • 使用JSX时,会转成React.createElement
  • React.memo的使用
  • 封装Provider组件,子组件采用
       
         {this.props.children}
       
    

1.4 参考的轮子

  • ahooks官网
  • lodash官网
  • react-fast-compare淘宝镜像
  • immutability-helper淘宝镜像

2. 已知会导致re-render的可能性

  1. 组件props变更()
  2. 组件监听的dva变更
  3. 组件监听的context变更
  4. 组件eventBus接受到消息
  5. 组件监听的state,用户会频繁操作,或一次操作,引发了多次setState,且不在一个effect中
  6. 父组件发生re-render
  7. 父组件包含自更新组件,比如key会变化

3. 解决方案

3.1 props的判定

React中将【属性】【函数】【children】,统一传递给props
属性(React.memo(组件名, (prev, next) => {}))+ 回调函数(useCallbackuseMemoziedFn)

  • 对于【基本数据类型】而言,直接使用React.memo包裹即可
  • 对于【复杂数据类型】而言,需要传递第二个参数进行判定,函数返回false会进行re-render
    function areEqual(prevProps, nextProps) {
      /*
      如果把 nextProps 传入 render 方法的返回结果与
      将 prevProps 传入 render 方法的返回结果一致则返回 true,
      否则返回 false
      */
    }
    export default React.memo(MyComponent, areEqual);
    
    • 深度比较prevnext的值是否相等
    • lodashisEqualreact-fast-compareisEqual
  • 对于【回调函数】而言,需要保证函数本身的指针不变(官方推荐采用useCallback)。但是若回调函数依赖外部变量,会使得指针发生改变,则失效;若不监听变量,则会产生问题,也失效。这时useMemoizedFn就有作用了

3.2 useSelector的使用

  • 不要返回大对象
    反例:
    const app = useSelector((state: { app: any }) => state.app) || {};
    
  • 利用第二个参数进行深度比较,来减少re-render

3.3 useContext的使用

  • 存储的属性颗粒度要小,不要直接存储大对象
  • 封装Provider

3.4 eventBus的使用

注销时,off消费函数

useEffect(() => { 
  EventEmitter.on('refreshTagList', refreshCbk); 
  return () => { 
    EventEmitter.off('refreshTagList', refreshCbk); 
  }; 
}, []);

3.5 本组件优化策略

  • usememo(降低非必要渲染)
  • useDebounceFn(防抖)
  • 多个setState合并
  • useUpdateEffect(减少初始化的不必要数据变更)

3.6 父组件re-render

同3.1策略

3.7 自更新组件

抽离出自更新组件到祖父级(最好存放在的组件中)

你可能感兴趣的:(【性能优化】降低re-render)