Привет! Сегодня поговорим про стандартные способы оптимизации web-приложения в экстремистской библиотеке React. Мотивацией послужило некоторое количество кода, который я видел. Связан он с использованием API React не по назначению или без учета каких-то очевидных проверок на производительность и тонкостей (с натяжкой). Самые популярные в React (говорим о версии 16.8+) функции для оптимизации: хуки useCallback и useMemo, метод React.memo. Разберемся для чего они. Его величество useCallback - возвращает мемоизированный колбэк. Неповторимый useMemo - возвращает мемоизированное значение. Господин High Order Component (HOC) React.memo - поверхностно сравнивает компоненты между отрисовками и если входные параметры (props) не изменились, то не вызывает рендер компонента, то есть мемоизирует компонент. Интересно, сколько начинающих разработчиков разбежалось после "мемоизация, мемоизация и еще раз мемоизация"? О том, что такое HOC сегодня говорить не будем, несложная концепция, связанная с композицией. По сути банальное кэширование значений. Да, вот так просто. Как это работает?  В документации в целом был описан алгоритм, по которому все работает. Напоминаю: в хуки useMemo и useCallback мы передаем вторым параметром массив зависимостей и если какая-то зависимость изменяется, то высчитываем значение заново (ну или пересоздаем функцию), если нет - возвращаем результат предыдущих вычислений. Так как нам очевидно, что если у нас есть переменная sum, которая содержит сумму чисел a и b, то нам не обязательно заново складывать a и b между рендерами, если мы это уже делали и переменные не изменились. По сути это и есть вся идея мемоизации, для лучшего понимания оставлю пример мемоизирования на чистом JS, вдруг кто-то еще не сталкивался. Получили: сокращение количество вызовов. А в чем подвох? Подвох в том, что кэш надо где-то хранить, спойлер: используется память, поэтому будьте аккуратнее, совсем не обязательно оптимизировать вызовы примитивных функций, который вызываются много раз. Приложение просядет по памяти. Создадим простое приложение а-ля to-do list и будем оптимизировать.    Что произойдет при запуске? Посмотрим в консоль. Ай-ай-ай, самое важное, добавить key. А теперь удалим элемент и посмотрим сколько раз вызовется функция/компонент Item. Окей, а как это исправить? Многие используют для этих целей useCallback и useMemo, ожидая, что это поможет, ну или код станет лучше работать. Давайте попробуем. Как думаете, что случится? Да ничего, вызовы будут такими же, вы просто мемоизировали функцию. А зачем? Вот и я думаю, что смысла в этом было мало. Причины: на рендерах это никак не отразилось вы увеличили стек вызова (useCallback каждый раз проверяет надо ли пересоздать функцию) в целом с таким же успехом можно было и пересоздать ее, перфоманс не уменьшится, может даже наоборот А как все-таки правильно? Тут в дело вступает React.memo, тот самый HOC, который мемоизирует компоненты. Окей, теперь все работает, по сути это и есть правильный пример использования, мемоизировать функции в большинстве случаев надо тогда, когда вы передаете их в мемоизированные компоненты. Кстати, а что насчет свойства key? Можете проверить сами, если его убрать, то useCallback и React.memo вам не помогут. А useMemo когда использовать? Точно также как и useCallback, ну или если вычисления сильно сложнее pages = Math.ceil(total / perPage). Всегда сначала думайте, а потом делайте. Оптимизация в какой-то мере искусство и требует опыта (ну например те же сложные вычисления всегда можно просто переложить на серверную часть, на курсах такому могут и не научить).  Однозначного ответа на то как правильно нет, ситуации бывают индивидуальные, но как неправильно часто становится ясно спустя пару потраченных минут на обдумывание того или иного действия. Спасибо за внимание!