函数式组件性能优化--避免不必要的重新渲染

294 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

一.React.memo基本使用

使用场景:

当你想要避免的子组件中的函数式组件接收父组件的props没有变化时产生的不必要更新,就要用到React.memo了

作用:

记忆组件上一次的渲染结果,在props没有变化时复用该结果,避免函数组件不必要的更新

格式:

const MemoChild=React.memo(Child)

解释:

  • React.memo是一个高阶组件,用于记忆(memorize)组件,memo其实就是memorize的简写
    
  • 参数(child)表示需要被记忆的组件即避免不必要更新的组件
    
  • 返回值(MemoChild)表示React记住的Child组件
    

子组件在实际应用中使用:

import React from 'react'
function Son() {
  。。。
}
export default React.memo(Son)

原理:

通过对比检测更新前后props是否相同来决定是否复用上一次的渲染结果

  • 如果相同则复用上一次的渲染结果

  • 如果不同则重新渲染组件

React.memo浅层对比的问题

import { useState } from 'react'
import Son from '/Son'

export default function Father(){
 const [num,setNum]=useState(1)
 const add=()=>{
  setNum(num+1)
 }
 return (
  <div>
     num:{num}<button onCilck={()=>setNum(num+1)}>num+1</button>
     <Son add={add} />
  </div>
 )
} 

由于add是定义的函数,而在整个组件重新渲染时,它也会被重新定义,所以它会导致Son组件的更新

useCallback

使用场景:

在使用React.memo时,为了组件每次更新时都能获取到相同引用的函数,就要用到useCallback Hook

作用:

记忆传入的回调函数,这个被记住的回调函数就会一直生效,直到依赖发生变化

格式:

const memoCallback=useCallback(()=>{

doSomething(a,b)
})

解释:

  • 参数1:必选,表示需要被记忆的回调函数

  • 参数2:必选,依赖项数组,用于指定回调函数中依赖(用到)的数据(类似于useEffect的第二个参数),即使没有依赖,也得传入空数组([ ]),此时,useCallback记住的回调函数就会一直生效

  • 返回值:useCallback记住的回调函数

useMemo

使用场景:

类似于useCallback,可以在组件更新期间保持任意数据引用相等,一般用来处理对象类型的数据

对比:

useCallback智能记忆函数,而useMemo可以记忆任意数据。

作用:

记忆任意数据,这个被记忆的数据就会一直生效,直到依赖项发生变化

语法:

const memoValue = useMemo(()=>需要被记住的数据,deps)

解释:

  •  参数1:必选,表示回调函数。注意:该回调函数会被调用,并通过返回值指定需要被记住的数据
    
  •  参数2:必选,表示依赖项数组,用于指定回调函数中依赖(用到)的数据。同样,没有依赖项目时,传入空数组
    
  • 返回值:useMemo记住的数据
    
  • useMemo的数据会一直生效(或者说会一直返回同一个数据),直到依赖项发生改变
    

总结:

在记忆数据时候,如果是函数则使用useCallback

如果是其他数据如对象时使用useMemo