Просто не добавляйте к классу методы public mutator (setter).
У вас есть дополнительные { }
после =>
, создавая таким образом блок и область, просто удалите их и тоже ;
, так как это делает это оператором. В противном случае передайте ему аргументы, используйте это
const memoizedCallback = useCallback(
() => doSomething(a, b)
,
[a, b]
);
В нем говорится undefined
, потому что область действия => { }
не получает a,b
. Надеюсь, это поможет.
Цель useCallback
- иметь возможность использовать реквизит или состояние, которые находятся в текущей области видимости и которые могут измениться при повторном рендеринге. Затем массив зависимостей сообщает React, когда вам нужна новая версия обратного вызова. Если вы пытаетесь запоминать дорогостоящие вычисления, вам нужно вместо этого использовать useMemo
.
Пример ниже демонстрирует различия между useCallback
и useMemo
и последствия их неиспользования. В этом примере я использую React.memo
для предотвращения повторного рендеринга Child
, если только его реквизиты или состояние не изменятся. Это позволяет увидеть преимущества useCallback
. Теперь, если Child
получит новый onClick
реквизит, это вызовет повторную визуализацию.
Дочерний элемент 1 получает незарегистрированный обратный вызов onClick
, поэтому всякий раз, когда родительский компонент выполняет повторную визуализацию, дочерний элемент 1 всегда получает новую функцию onClick
, поэтому он вынужден выполнять повторную визуализацию.
Ребенок 2 использует запомненный обратный вызов onClick
, возвращенный из useCallback
, а ребенок 3 использует эквивалент через useMemo
, чтобы продемонстрировать значение
useCallback (fn, input) эквивалентно useMemo (() => fn, input)
blockquote>Для дочерних элементов 2 и 3 обратный вызов по-прежнему выполняется каждый раз, когда вы нажимаете дочерний элемент 2 или 3,
useCallback
просто гарантирует, что один и тот же версия функцииonClick
передается, когда зависимости не изменились.Следующая часть дисплея помогает указать, что происходит:
nonMemoizedCallback === memoizedCallback: false | true
blockquote>Отдельно я Отображаю
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);
Вот связанный ответ: React Hooks useCallback заставляет дочерний процесс перерисовывать