Улучшение вашей ментальной модели использования
Хуки появились в React несколько месяцев назад, и вокруг них было много волнения с точки зрения выяснения того, как их лучше всего использовать, передовых практик и того, как они соотносятся с текущими концепциями в React и жизненном цикле.
Многие разработчики React знакомы с жизненным циклом компонентов React и такими хуками, как:
Когда вы пытаетесь понять ловушку useEffect, естественно захотеть сопоставить ее с методами жизненного цикла, которые мы уже знаем. На первый взгляд useEffect выглядит как комбинация componentDidMount и componentDidUpdate.
Хотя на первый взгляд это может быть полезным способом взглянуть на него, он может быть не самым точным.
Вместо того чтобы думать о том, «что я хочу делать, когда я подключаюсь или обновляю», полезнее спросить:
От каких значений зависит этот эффект?
Чтобы лучше понять, откуда взялась идея useEffect = componentDidMount + componentDidUpdate, мы сначала рассмотрим типичный компонент на основе классов, который выполняет некоторую выборку данных.
Когда компонент монтируется впервые, мы получаем данные для идентификатора, который был передан в качестве опоры. Когда компонент обновляется, поскольку многие вещи, помимо изменения пропуска идентификатора, могут вызвать запуск этого метода, мы хотим убедиться, что идентификатор действительно изменился - иначе какой-то плохой сервер получит DDoS-атаку с кучей вызовов API, которые нам не нужно.
Хотя хуки жизненного цикла componentDidMount и componentDidUpdate с компонентами на основе классов являются обычными местами для выполнения запроса на основе свойства, тот факт, что компонент монтируется или обновляется, не действительно то, что нас беспокоит.
Что нас волнует: «от каких данных зависит запрос?»
Прежде чем смотреть, как справиться с этим с помощью useEffect, давайте быстро рассмотрим API useEffect:
- Принимает функцию
- Если он возвращает функцию, он выполнит очистку при размонтировании компонента.
- Имеет необязательный второй аргумент для передачи данных, от которых он зависит
Одна из ключевых вещей, о которых следует помнить, - это важность второго аргумента, React Docs подробно описывает это, но вкратце:
- Если оставить поле пустым - он будет запускаться при каждом рендере.
- Если мы передадим пустой массив - он будет выполняться только при монтировании компонента, а не при каких-либо обновлениях
- Если мы передадим значение - оно будет выполняться при изменении любого из этих значений.
- Если вы используете react-hooks eslint plugin (и вы должны это сделать) - отсутствие зависимостей для вашего useEffect приведет к предупреждению.
В версии на основе классов выполнение вызовов API кажется крайне необходимым - когда вызывается этот метод, я хочу проверить, изменилось ли / как значение, и если оно изменилось - я хочу вызвать метод.
Неважно, часто ли компонент создается или обновляется. Что нас на самом деле волнует, так это «изменились ли ценности, которые меня волнуют?».
До появления хуков componentDidMount и componentDidUpdate были лучшими инструментами для работы в то время.
С версией на основе ловушки мы можем выразить это намерение более декларативно: «Я хочу получать данные при изменении идентификатора»
Как определить, от чего зависит эффект?
Плагин eslint может направить вас в правильном направлении, но его краткая версия: «есть ли переменная, которая влияет на то, как мы запускаем эффект?» Если да, добавьте его в зависимости.
Чтобы продемонстрировать это, давайте добавим в наш поиск дополнительный параметр запроса:
Несмотря на то, что мы добавили filter в строку запроса выборки, мы не добавили его в зависимости useEffect. При обновлении фильтра мы не будем вызывать API для других обновлений, и он будет запускаться только при изменении идентификатора.
Исправить это достаточно просто - просто добавьте фильтр в список зависимостей данных для useEffect.
Как видите, для правильного использования useEffect в этом случае нам все равно, монтируется ли компонент, обновляется или где он находится в жизненном цикле - нас действительно волнует то, что data зависит ли этот эффект от.
useEffect - очень полезный инструмент, который можно добавить к нашему набору инструментов при работе с React, но он также может быть одним из наиболее сложных приемов для понимания.
Надеюсь, этот пост поможет прояснить ситуацию немного лучше, но если вам интересно более глубокое погружение, обязательно ознакомьтесь с постом Дэна Абрамова Полное руководство по использованию эффекта