#javascript #reactjs #react-hooks #reducers
#javascript #reactjs #реагирующие перехваты #редукторы
Вопрос:
Для еще большей оптимизации / общей логики я хочу создать useSelectors
продукт, который использует многократный обратный вызов.
Здесь useSeletors
нужно включить селекторы (как в redux) useReducer
. Итак, это мой код :
const useSelectors = (state, selectors) => useMemo(
() => selectors.map(selector =>
(...args) => (selector(state, ...args))
),
[state]
);
Что я хотел сделать, так это :
const useSelectors = (state, selectors) => useMemo(
() => selectors.map(selector => useCallback(
(...args) => (selector(state, ...args))),
[state]
),
[state]
);
Что на самом деле вызывает ошибку.
Вероятно, я смогу это сделать :
const useSelectors = (state, selectors) => useMemo(
() => selectors.map(selector => selector(state)),
[state]
);
Но я теряю возможность использовать аргументы для моей функции выбора.
Может быть, это не проблема, потому что есть кое-что, чего я пока не понимаю, о useCallback
:
Если я использую a useCallback
без указания аргументов, но с указанием зависимости, это будет почти как переменная.
Выполняется ли он при первом вызове? В следующий раз (без обновления зависимости) я напрямую получаю возврат функции без выполнения?
Итак, что произойдет, если я добавлю переменные аргументы (например, счетчик) в обратный вызов?
вероятно, он повторно выполнит функцию с этим новым аргументом, даже если зависимость не изменится?
Так что useCallback
, структура стала бесполезной с аргументами?
Последний момент, который я хочу спросить: когда выполняется обратный вызов?
Для a useMemo
функция выполняется в первый раз при объявлении is ? (Или в первый раз, когда мы используем его переменную? => Разница в данном случае не очень важна.)
Did useCallback
вызывается в первый раз только тогда, когда он вызывается с ()
помощью в коде или при его объявлении?
Пример :
const myVar = useMemo(() => 5 5, [dependency]); // executed
const myFunc = useCallback(() => 5 5, [dependency]);
myVar; // 10
myFunc(); // executed => 10
myVar; // 10
myFunc(); // 10
Так что, если это работает так, лучше вызвать useCallBack
useMemo
, чтобы выполнить селектор только тогда, когда он вызывается, а не при монтировании в моем третьем решении.
Это основная причина, по которой я хочу использовать multiple useCallbacks
в своем перехвате, не зная номера.
[ПРАВИТЬ / ПРАВИТЬ код]
Второе предложение с useCallback не имеет смысла, потому что :
const test = useCallback(() => {
console.log('test is executed');
return 'test';
}, [state]);
console.log(test());
console.log(test());
Журналы :
тест выполняется
тест
выполняется тест выполняется
тест
И не то, что я ожидал :
тест выполняется
тестовый
тест
Так что он не может быть лучше, чем первый
Ответ №1:
useCallback
возвращает функцию. Когда одна из зависимостей этого перехвата (например, некоторый счетчик) изменяется useCallback
, вызывается снова и возвращает новую функцию. Это происходит потому, что переданная функция useCallback
не знает, что счетчик изменен, пока useCallback
не выполнит его повторно.
useMemo
работает так же, но возвращает значение. Теоретически вы можете реализовать useCallback
использование useMemo
, возвращая функцию вместо значения. Я имею useCallback(fn, deps)
в виду то же useMemo(() => fn, deps)
самое, что и .
Вы можете прочитать больше об этом в документах React .
В вашем коде вы должны использовать useMemo
и не использовать useCallback
inside useMemo
, потому что вы получите ошибку, и это не лишнее, потому что оно используется при передаче обратных вызовов оптимизированным дочерним компонентам, которые полагаются на равенство ссылок для предотвращения ненужного рендеринга. Это не ваш случай. Ваш первый пример кода правильный.
Комментарии:
1. Я уже прочитал документ, но я, вероятно, переоценил useCallback