Как продвинутым React-разработчикам стоит мыслить о хуках
Большинство разработчиков изучают хуки, не понимая, как React выполняет рендеринг. Это вызывает путаницу. Чтобы освоить хуки, необходимо понимать пять основных задач:
• Сохранение данных • Выполнение побочных эффектов • Передача данных • Оптимизация рендеринга • Управление планированием (scheduling)
Изменения состояния вызывают рендеринг. Каждый рендеринг заново создает переменные, объекты и функции. Этот простой факт объясняет, зачем нужны useMemo и useCallback.
Понимание хуков
Состояние и порядок вызова
React хранит состояние в связном списке, прикрепленном к Fiber-узлу компонента. Именно поэтому нельзя вызывать хуки внутри условий или циклов. React полагается на порядок вызовов, чтобы найти правильное состояние.
Реальность батчинга
Когда вы вызываете setState, React планирует обновление. Он не меняет значение мгновенно. Именно поэтому логирование состояния сразу после его установки показывает старое значение. Всегда используйте паттерн функционального обновления, чтобы избежать использования устаревших данных:
- Плохо:
setCount(count + 1) - Хорошо:
setCount(prev => prev + 1)
Ментальная модель useEffect
Перестаньте относиться к useEffect как к методу жизненного цикла. Используйте его для синхронизации вашего компонента с внешними системами, такими как API или WebSockets.
Важно: React отрисовывает экран до того, как сработает useEffect. Это гарантирует, что ваш эффект не заблокирует пользовательский интерфейс. Если вам нужно измерить DOM до того, как пользователь его увидит, используйте useLayoutEffect.
Реальность useRef
Ref — это не только для DOM-элементов. Это постоянный мутабельный контейнер. React сохраняет одну и ту же ссылку на объект между рендерингами. Изменение ref.current не вызывает рендеринг. Используйте его для таймеров, сокетов или хранения предыдущих значений.
Ловушка мемоизации
useMemo — это не волшебная кнопка для ускорения. У него есть накладные расходы. React должен сохранять кэш и сравнивать зависимости.
Используйте useMemo только в том случае, если стоимость вычислений выше, чем стоимость мемоизации. Если вы используете его для простых математических операций, вы только замедлите приложение.
Context — это не управление состоянием
Context предназначен для внедрения зависимостей (dependency injection). Он помогает избежать прокидывания пропсов (prop drilling). Однако при изменении значения Context каждый потребитель (consumer) перерисовывается. Не помещайте всё глобальное состояние в один провайдер. Разделяйте контексты по назначению.
Продвинутые паттерны
• useReducer: используйте его для сложных конечных автоматов вместо множества вызовов useState.
• startTransition: используйте его, чтобы интерфейс оставался отзывчивым во время тяжелых обновлений.
• useDeferredValue: используйте его, чтобы отложить ресурсозатратные обновления интерфейса, пока пользователь вводит текст.
Пишите чистый код, вынося логику в пользовательские хуки. Компонент на 1200 строк трудно поддерживать. Пять небольших хуков, отвечающих за логику, легко масштабировать.
Источник: https://dev.to/jagadeesh_008/how-advanced-react-developers-should-think-about-hooks-102l