useMemo&useCallback

136 阅读2分钟

用法

useMemo和useCallback接收的参数都是一样,第一个参数为回调,第二个参数为要依赖的数据
共同作用:1. 仅仅依赖数据发生变化,才会重新计算结果,也就是起到缓存的作用。
俩者区别:1. useMemo计算结果是return回来的值,主要用于缓存结果的值,应用场景如:需要计算的状态。
    2. useCallback计算结果是函数,主要用于缓存函数,应用场景如:需要缓存的函数,因为函数式组件每次任何一个state的变化整个组件都会被重新刷新,一些函数是没有必要被重新刷新的,此时就应该缓存起来,提高性能,和减少资源浪费。

useCallback

代码示例
import React, { useEffect, useState, useCallback, useMemo } from 'react';


const App = () => {
const [count, setCount] = useState(0);
// 使用 useCallBack 缓存
const handleCountAddByCallBack = useCallback(() => {
    setCount((count) => count + 1);
  }, []);

  // const handleCountAddByCallBack = () => {
  //   setCount((count) => count + 1);
  // };

// 不缓存,每次 count 更新时都会重新创建
  const handleCountAdd = () => {
    setCount((count) => count + 1);
  };
  
return (
    <>
    <h3>CountAddByChild1: {count}</h3>
     <Child1 addByCallBack={handleCountAddByCallBack} add={handleCountAdd} />
    </>
 )
}

const Child1 = ({ addByCallBack, add}) => {
// 没有缓存,由于每次都创建,memo 认为两次地址都不同,属于不同的函数,所以会触发 useEffect
  useEffect(() => {
    console.log("Child1----addFcUpdate");
  }, [add])

// 有缓存,memo 判定两次地址都相同,所以不触发 useEffect
  useEffect(() => {
    console.log("Child1----addByCallBackFcUpdate");
  }, [addByCallBack])
  return (
    <div>
      <Button onClick={add}>+1</Button>
      <br />
      <Button onClick={addByCallBack}>+1(addByCallBack)</Button>
    </div>
  )
}

useMemo

代码示例
const Child1 = () => {
  const [count, setCount] = useState(0);
  const [total, setTotal] = useState(0);
  // 没有使用 useMemo,即使是更新 total, countToString 也会重新计算
  const countToString = (() => {
    console.log("countToString 被调用");
    return count.toString();
  })();

  // 使用了 useMemo, 只有 total 改变,才会重新计算
  const totalToStringByMemo = useMemo(() => {
    console.log("totalToStringByMemo 被调用");
    return String(total);
  }, [total]);
  return (
    <div>
      <h3>countToString: {countToString}</h3>
      <h3>countToString: {totalToStringByMemo}</h3>
      <Button
        onClick={() => {
          setCount((count) => count + 1);
        }}
      >
        Add Count
      </Button>
      <br />
      <Button
        onClick={() => {
          setTotal((total) => total + 1);
        }}
      >
        Add Total
      </Button>
    </div>
  )
}
小结
  1. useCallBack针对可能重新创建的函数进行优化,使得函数被缓存,React.memo认定俩次地址是相同就可以避免子组件冗余的更新。
  2. useMemo针对不必要的计算进行优化,避免了当前组件中一些冗余计算操作。