Главная Категории Контакты Поиск

useCallback и useMemo

Когда нужно использовать useCallback и useMemo

React·25.02.2021·читать 2 мин 🤓·Автор: Alexey Myzgin

В документации React есть только один намёк:

useCallback(fn, deps) эквивалентен useMemo(() => fn, deps).

Что делает useMemo

Короче говоря, useMemo вызывает функцию при изменении зависимостей и memoizes (запоминает) результат функции между рендерами.

В этом и есть отличие от useCallback, которая запоминает существующее значение (обычно определение функции) между рендерами.

Тебе стоит использовать useMemo, чтобы избежать повторного выполнения дорогостоящих вычислений для генерации нового значения, а useCallback стоит использовать для сохранения существующего значения.

Когда использовать useMemo

В этой части легко заблудиться. Есть много статей, в которых описывается useMemo, а затем приводятся примеры того, когда его не следует использовать.

К сожалению, нужно повторить: не используй useMemo, пока не заметишь, что части приложения работают очень медленно. «Преждевременная оптимизация - это корень всех зол», а повсюду бросать useMemo - это преждевременная оптимизация.

Вот несколько случаев, когда тебе следует рассмотреть возможность использования useMemo:

  • ты замечаешь, что рендеринг компонента происходит очень медленно, и ты передаешь вычисление неизвестному количеству дочерних элементов, например: при рендеринге дочерних элементов с помощью Array.map()
  • твое приложение часто перестает отвечать, потому что ты получаешь большой объем данных и необходимо преобразовать их в пригодный для использования формат.

Главное - сосредоточиться на проблеме.

«Мое приложение работает медленно и требует больших вычислений» - это проблема, которую помогает решить useMemo. Запусти приложение через React DevTools Profiler, а также через Google Lighthouse или WebPageTest, чтобы понять показатели производительности, оберни свои вычисления в useMemo, а затем измерь ещё раз.

«Я только что изучил useMemo и хочу использовать его повсюду» - хоть ты и сосредоточен на решении, но это приведет тебя к преждевременной оптимизации и потенциально более медленному приложению.

Почему бы тогда не использовать useMemo везде?

Короче говоря, это не бесплатная оптимизация производительности.

При настройке useMemo возникают дополнительные затраты (например, использование памяти), которые могут очень быстро перевесить выигрыш в производительности от запоминания возможных значений каждой отдельной функции.

Когда мы используем useMemo, мы занимаем больше памяти, чтобы освободить время процессора. Если твое приложение забивает процессор большим количеством вычислений, тогда можно подумать о том, чтобы занять некоторую память и вместо этого использовать useMemo.

А как насчет стабильных ссылок?

Если ты хочешь сохранить стабильную ссылку на объект / массив, не требующий пересчета, рассмотри возможность использования useRef.

С другой стороны, если нужно пересчитать значение при изменении зависимостей, useMemo - это то, что тебе нужно.

Возможные ошибки при использовании useMemo

Использование useMemo также не лишено ловушек. Одна из самых больших заключается в том, что кеш не гарантирует сохранения всех своих значений между рендерами. Взято из документации:

"You may rely on useMemo as a performance optimization, not as a semantic guarantee"

Ты можешь полагаться на useMemo как на оптимизацию производительности, а не как на семантическую гарантию.

Иными словами: кеш нестабилен!

Это означает, что если ты абсолютно не хочешь повторных вычислений с помощью вызова useMemo, то это не гарантируется. Для версии useMemo со стабильным кешем смотри UseMemoOne.

Website, name & logo
Copyright © 2022. Alex Myzgin