#javascript #reactjs #react-hooks #usecallback
#javascript #reactjs #реагирование-перехваты #usecallback
Вопрос:
TL; DR
В некоторых блогах говорится, что вам не нужно использовать useCallback
перехват каждый раз, когда вы передаете обратный вызов дочернему компоненту, и иногда лучше каждый раз создавать новую функцию. Потому что стоимость useCallback
иногда выше, чем фактическая проблема с производительностью. В то время как React предупреждает, что это может привести к проблемам с производительностью, и мы должны попытаться избежать этого.
Кто прав и каков баланс между этими двумя противоположными утверждениями?
Полный вопрос
В последнее время я читал много блогов и руководств о реактивных перехватах, особенно об useCallback
и useMemo
.
До React 16 (и всех его перехватов), когда я использую компоненты класса, я всегда использовал «привязку конструктора» для своих обратных вызовов, потому что функция arrow или «Привязка в рендеринге», подобные этим:
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>;
}
Рассматривались как «плохая практика». Из React Docs:
Использование Function.prototype.bind при рендеринге создает новую функцию каждый раз при рендеринге компонента, что может повлиять на производительность (см. Ниже).
Использование функции со стрелкой в рендеринге создает новую функцию каждый раз при рендеринге компонента, что может нарушить оптимизацию, основанную на строгом сравнении идентификаторов.
Итак, моим эмпирическим правилом было не передавать новые функции в props.
В React 16 useCallback
хук пытается помочь нам сделать именно это. Но я вижу много подобных блогов, в которых утверждается, что вам не нужно использовать useCallback
хук каждый раз, потому что стоимость useCallback
иногда выше, чем фактическая проблема, и использование функций со стрелками, которые создают новую функцию при каждом рендеринге, подходит.
Оба противоположных утверждения заставили меня подумать, что лучшим вариантом должно быть что-то вроде (если массив зависимостей пуст):
function handleCallback() { ... } // Or arrow function...
function Foo(props) {
return <button onClick={handleCallback}>Click Me</button>
}
Потому что этот способ не использует «дорогой» useCallback
и не генерирует новую функцию каждый раз. Но, на самом деле, этот код выглядит не так хорошо, когда у вас есть несколько обратных вызовов.
Итак, каков правильный баланс между этими двумя противоположными утверждениями? Если создание новой функции каждый раз иногда лучше, чем использование useCallback
, почему у React есть предупреждение в их документах об этом?
(Тот же вопрос о эмпирическом правиле «двойные фигурные скобки» и useMemo
/ useRef
hooks)
Комментарии:
1. Ваш подход с
function handleCallback
внешней стороныFoo
компонента, безусловно, оптимален, но не работает, если обратному вызову требуется доступ и реквизиты или состояние.2. Верно, но когда у вас есть зависимости от состояния или реквизита, вы, вероятно, будете использовать
useCallback
, потому что его «механизм зависимостей». Интересный случай, когда у вас есть обратный вызов без зависимостей.3. В этом случае отдельная функция — лучший способ перейти к imo. Я не понимаю, почему вы считаете, что » этот код выглядит не так хорошо «.
4. Когда у вас есть несколько обратных вызовов к одному компоненту, несколько функций в этом файле иногда «скрывают» саму функцию компонента. Ничего страшного… Что-то с
useCallback
немного более элегантным для меня 🙂