1.问题背景
- 当我遇到地图组件时候,React重复渲染,使得页面变得非常卡顿。
- 有很多没有意义的渲染,比如在数据为空的时候,或者由父组件引起的渲染,但是当前组件props没有改变。
- 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'