React 系列 - useMemo 与 useCallback

237 阅读2分钟

前言

一直以来对React Hooks的解读不够,导致一些场景的使用上可能会不合时宜,  
本文主要是围绕`useMemo`与`useCallback`两个hook,基于疑问三连(what? why? where?)的方式进行解读  
本文提到的这两个hook主要的场景是用到性能优化上面,但请切记:合理的场景使用性能优化才是最有效的

简介-React Hooks

  • React Hooks是react16.8之后引入的新特性。
  • React Hooks允许支持了在函数组件使用React的状态及其特性。
  • React Hooks让函数组件有了类组件的能力。
  • 可以更方便的使用函数组件抽离/封装一些公共能力。
  • 简化了一些业务逻辑和代码复杂度。

useMemo是什么?

  1. useMemo是众多的Hooks之一,用来缓存计算结果,避免重复的计算
  2. 基本定义
// 伪代码
function useMemo(create:()=>mixed, deps:Array<mixed>): create() {//...}
  • 通过上面的代码可以了解到,useMemo有两个参数,create:必传参数,是一个函数,deps:非必传参数,依赖数组。返回值 create的最新计算结果或缓存的计算结果

useMemo使用场景

  • 缓存对象Object数据或者map数据
  • 性能优化:父组件更新,缓存子组件,避免父组件更新带来的不必要更新
  • 性能优化:当存在大量的复杂计算场景时。
  • 场景代码示例(当前仅示例父组件更新影响子组件)
    • 根据react组件渲染机制,在没有任何处理的情况下,父组件渲染必然会引起子组件的重新渲染,而对于子组件来讲props不变的情况下不需要这种无效的更新,此时就可以使用useMemo进行优化。
      
       // 父组件
       const App = () =>{
           const [a, setA] = useState(0);
           const [title, _] = useState("我是子组件的props")
               
           return <>
                   <button onClick={()=>setA((v)=>v+1)}>点击增加1</button>
                   <Child title={title}/>
                  </>
       }
       
       
       // 优化前 子组件
       const Child = (props) =>{
           return <div>{props.title}</div>
       }
       export default Child;
    
       // 优化后 子组件
       const Child = (props) =>{
           return <div>{props.title}</div>
       }
       export default useMemo(Child); // 改变的是这里
    

useMemo源码实现更新流程

image.png

useCallback是什么?

  1. useCallback是众多的Hooks之一,用来缓存函数(同样可以缓存函数组件),避免渲染时重复创建函数
  2. 基本定义
// 伪代码
function useCallback(callback:()=>mixed, deps:Array<mixed>): callback {//...}
  • 通过上面的代码可以了解到,useCallback有两个参数,callback:必传参数,是一个函数,deps:非必传参数,依赖数组。返回值 最新的callback函数或缓存的callBack函数

useCallback使用场景

  • 父组件将函数做为props传给子组件时,避免子组件更新
  • 组件渲染时,不需要重复新建的函数(适用于场景复杂度高但依赖清晰的函数)

useCallback源码实现更新流程

image.png