是谁,让我的React组件重复render

1,169 阅读2分钟

1.问题背景

  1. 当我遇到地图组件时候,React重复渲染,使得页面变得非常卡顿。
  2. 有很多没有意义的渲染,比如在数据为空的时候,或者由父组件引起的渲染,但是当前组件props没有改变。
  3. props里的值存在引用,所以父组件re-render时候,引用地址变化了,也会导致子组件重新渲染。

2. Why did you render 工具介绍

当我在开发 React 项目时,经常会想,要是有一个工具能实时告知我组件是否有性能问题就好了,这样就能在开发的时候就尽量避免组件过大时的性能问题,以及降低潜在的页面崩溃概率。 然后我就在网上找到了这个工具:@welldone-software/why-did-you-render,它能在我开发 react 组件的时候及时提醒我当前写的组件是否有不必要的重复渲染问题,在开发的时候就避免掉部分性能问题。

why did you render 应当在开发环境里使用。

为避免麻烦,以下why did you render 都简称 why render。

core-js 在3.0版本以上

(1).安装

npm install @welldone-software/why-did-you-render --save
yarn add @welldone-software/why-did-you-render -D

引入

import React from 'react'
if (!isProduction) {
  const whyDidYouRender = require('@welldone-software/why-did-you-render')
   whyDidYouRender(React, {
     trackAllPureComponents: true
   })
}

启动项目,查看控制台

3. 优化方法

(1). class组件

可以安装一个插件 memoize-one

  import memoize from 'memoize-one'
    
  memoizeMapValue = memoize(() => {
    const { style, mapInfo } = this.props
    const { mapId, appName, appKey } = mapInfo
    return {
      defaultThemeName: mapId,
      appName,
      appKey,
      mapId,
      mapServerURL: MAP_URL + '/maps',
      mapThemeURL: MAP_URL + '/themes',
      supportTxt: formatMessage({ id: 'DESKING_MAP_IN_BOWER' }),
      loadingTxt: formatMessage({ id: 'DESKING_DESK_LOADING' }),
      style,
      loadComplete: this._onMapLoaded,
      mapClickNode: this._onFidClicked,
      lazyCreateMode: false
      // tile: true
    }
  })

将值缓存下来,对于同一个参数,出现两次时,会直接使用上次计算缓存的结果。

(2). hooks组件

import { useMemo } from 'React'

插件npm地址

插件github地址