Массив зависимостей

Тема дорожной карты · React

Массив зависимостей useEffect — это второй аргумент хука useEffect, управляющий повторным запуском эффекта путём перечисления всех реактивных значений, которые эффект читает из области видимости компонента. Когда массив зависимостей пуст ([]), эффект запускается только один раз после первоначального рендера; когда в нём перечислены конкретные переменные состояния или пропсы, React повторно запускает эффект при изменении любого из этих значений между рендерами. Полное отсутствие массива зависимостей заставляет useEffect запускаться после каждого рендера, что редко бывает намеренным и часто приводит к проблемам производительности или бесконечным циклам в React-компонентах. React ESLint-плагин (eslint-plugin-react-hooks) применяет правило exhaustive-deps, предупреждая об отсутствующих реактивных значениях в массиве зависимостей. Правильное управление массивом зависимостей useEffect — один из наиболее важных и тонких навыков при разработке на React-хуках, напрямую влияющий на корректность, производительность и поведение управления состоянием.

Как это работает

Массив зависимостей строится на useState для локального состояния компонента и useEffect для сайд-эффектов (мутации DOM, подписки, сеть). useState(initial) возвращает [value, setValue]; вызов setValue(next) планирует ререндер. useEffect(fn, deps) запускает fn после рендера при изменении любого элемента deps; возврат функции из fn регистрирует cleanup. Хуки должны вызываться в одном и том же порядке каждый рендер — никогда внутри if или циклов.

Когда применять

useState — для состояния одного компонента (toggle, поля формы, hover). Поднимайте state к ближайшему общему предку, когда двум компонентам нужно его делить. useEffect — для сайд-эффектов (подписки, синк, фетч), не для производных значений (считайте их inline) или трансформации props (делайте на рендере). Пустой deps=[] запускает один раз на mount; пропущенные deps — эффект на каждый рендер (почти всегда ошибка).

Типичные ошибки

Ловушки Массив зависимостей: stale closures (setCount(count + 1) ловит count этого рендера — используйте setCount(c => c + 1)); пропущенные deps и эффекты на каждый рендер; чрезмерный useEffect для того, что React делает сам (computed values, зеркалирование props); неверный cleanup (подписка осталась = утечка памяти при unmount). Прочтите гайд "You Might Not Need an Effect" — он убирает половину useEffect в реальных кодовых базах.

Связанные понятия

Полезные ресурсы