目的
useCallback是能够利用当前范围内的道具或状态,并且在重新渲染时可能会更改。然后,依赖项数组会告诉React什么时候需要新版本的回调。如果您想记住昂贵的计算,则需要使用
useMemo。
下面的示例演示了之间的区别
useCallback以及
useMemo不使用它们的后果。在此示例中,除非属性或状态发生变化,否则我
React.memo将阻止
Child重新渲染。这样可以看到的好处
useCallback。现在,如果
Child收到新的
onClick道具,它将导致重新渲染。
子项1正在接收非内存
onClick回调,因此,每当父组件重新呈现时,子项1始终会收到一个新
onClick函数,因此被迫重新渲染。
子级2正在使用从中
onClick返回的记忆回调,
useCallback而子级3正在使用等效的via
useMemo来演示的含义。
useCallback(fn,输入)等同于useMemo(()=> fn,输入)
对于子级2和3,每次单击子级2或3时,回调仍将执行,
useCallback只需确保在
onClick不更改依赖项的情况下传递相同版本的函数。
屏幕的以下部分有助于指出正在发生的事情:
nonMemoizedCallback === memoizedCallback:false | true
另外,我正在显示
somethingExpensivebasedOnA和的备忘版本
useMemo。出于演示目的,我使用了不正确的依赖项数组(我有意省略了
b),以便您可以看到记住的版本在更改时不会
b更改,但是在更改时会
a更改。非存储版本会随时更改
a或
b更改。
import ReactDOM from "react-dom";import React, { useRef, useMemo, useEffect, useState, useCallback} from "react";const Child = React.memo(({ onClick, suffix }) => { const numRendersRef = useRef(1); useEffect(() => { numRendersRef.current++; }); return ( <div onClick={() => onClick(suffix)}> Click Me to log a and {suffix} and change b. Number of Renders:{" "} {numRendersRef.current} </div> );});function App(props) { const [a, setA] = useState("aaa"); const [b, setB] = useState("bbb"); const computeSomethingExpensivebasedOnA = () => { console.log("recomputing expensive thing", a); return a + b; }; const somethingExpensivebasedOnA = computeSomethingExpensivebasedOnA(); const memoizedSomethingExpensivebasedOnA = useMemo( () => computeSomethingExpensivebasedOnA(), [a] ); const nonMemoizedCallback = suffix => { console.log(a + suffix); setB(prev => prev + "b"); }; const memoizedCallback = useCallback(nonMemoizedCallback, [a]); const memoizedCallbackUsingMemo = useMemo(() => nonMemoizedCallback, [a]); return ( <div> A: {a} <br /> B: {b} <br /> nonMemoizedCallback === memoizedCallback:{" "} {String(nonMemoizedCallback === memoizedCallback)} <br /> somethingExpensivebasedOnA: {somethingExpensivebasedOnA} <br /> memoizedSomethingExpensivebasedOnA: {memoizedSomethingExpensivebasedOnA} <br /> <br /> <div onClick={() => setA(a + "a")}>Click Me to change a</div> <br /> <Child onClick={nonMemoizedCallback} suffix="1" /> <Child onClick={memoizedCallback} suffix="2" /> <Child onClick={memoizedCallbackUsingMemo} suffix="3" /> </div> );}const rootElement = document.getElementById("root");ReactDOM.render(<App />, rootElement);


