useMemo/useCallback/React.memo

返回一個 memoized

// useMemo返回一個值(可以是函數)
const computeExpensiveValue = (a, b) => {
    return a + b;
}
const memoizedValue = useMemo(computeExpensiveValue(a, b), [a, b]);


// useCallbak返回一個函數
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
  • useMemo和useCallback解決的因函數更新而渲染自己的問題
  • 它僅會在某個依賴項改變時才重新計算 memoized 值
  • 傳入 useMemo 的函數會在渲染期間執行
  • 副作用屬于 useEffect 的適用范疇,而不是 useMemo
  • 如果沒有提供依賴項數組,useMemo 在每次渲染時都會計算新的值
  • useCallback(fn, deps) 相當于 useMemo(() => fn, deps)

與React.memo的區別

  • react.memo解決的是因父組件state變化因為的自組件重復刷新的問題
  • React.memo的用法
function MyComponent(props) {
  
}
function areEqual(prevProps, nextProps) {
  // 手動判斷是否需要重新渲染
  // return true不渲染,false則渲染
}
export default React.memo(MyComponent, areEqual);

問題

  1. React.memo 第二個參數不用的話默認就 props 淺比較
  2. React.memo 在跟某些hooks配合使用的情況下會失效,例如在組件內部使用 useStateuseReduceruseContext ,當 state 或者 context 改變時,組件還是會重新渲染
import React, { useState } from "react";
function Child1(props) {
  console.log("執行子組件1了");
  return <div>子組件1上的n:{props.value}</div>;
}
function Child2(props) {
  console.log("執行子組件2了");
  return <div>子組件2上的m:{props.value}</div>;
}

const MChild1 = React.memo(Child1, () => {
    return false; // 失效
}); // compare失效會直接導致整個React.memo失效
const MChild2 = React.memo(Child2);

export default function App() {
  const [n, setN] = useState(0);
  const [m, setM] = useState(10);
  console.log("執行最外層盒子了");
  // 這里與是否是箭頭函數無關
  function addM() {
    setM(m + 1);
  }
  // 只要是復雜類型,都會渲染
    const test = { a: 134 }; // 如果test是簡單類型,則不會重復渲染
  return (
    <>
      <div>
        最外層盒子
        <MChild1 value={n} test={test}/>
        <MChild2 value={m} addM={addM} />
        <button
          onClick={() => {
            setN(n + 1);
          }}
        >
          n+1
        </button>
        <button
          onClick={addM}
        >
          m+1
        </button>
      </div>
    </>
  );
}

問題

  1. 自定義的compare函數失效,導致整個React.memo失效
  2. App重新執行了,它會修改復雜數據類型的地址,從而引發重新渲染
  • useMemo解決addN和addM地址變更引發的重復渲染的問題
import React, { useState, useMemo, useCallback, memo } from "react";
const Child1 = memo((props) => {
  console.log("執行子組件1了");
  return <div>子組件1上的n:{props.value}</div>;
})

const Child2 = memo((props) => {
  console.log("執行子組件2了");
  return <div>子組件2上的m:{props.value.m}</div>;
})

export default function App() {
  const [n, setN] = useState(0);
  const [m, setM] = useState({ m: 1 });
  console.log("執行最外層盒子了");
  const addN = useMemo(() => {
    return () => {
      setN(n + 1);
    };
  }, [n]);
  const addM = useCallback(() => {
    setM({ m: m.m + 1 });
  }, [m]);
  return (
    <>
      <div>
        最外層盒子
        <Child1 value={n} click={addN} />
        <Child2 value={m} click={addM} />
        <button onClick={addN}>n+1</button>
        <button onClick={addM}>m+1</button>
      </div>
    </>
  );
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容