Почему для внешних функций не нужен массив зависимостей в useEffect?
Что проверяют
Понимаете ли вы, что именно попадает в зависимости и почему. Правило одно: в массив идёт всё реактивное, то есть способное отличаться между рендерами. Функция, объявленная вне компонента, между рендерами одна и та же, и добавление её в массив не меняет ничего.
Как отвечать
Начните с механики. Значения из массива сравниваются через Object.is со значениями предыдущего рендера, и если хоть одно изменилось, эффект перезапускается. Функция, объявленная внутри компонента, создаётся заново на каждом рендере, ссылка каждый раз новая, поэтому без useCallback она заставит эффект срабатывать бесконечно. Функция за пределами компонента создаётся один раз при вычислении модуля, ссылка стабильна, сравнивать нечего.
function fetchStats(id) { /* ... */ }
function Stats({ id }) {
useEffect(() => {
fetchStats(id).then(setData);
}, [id]);
}То же касается импортов, значения ref и функций-сеттеров из useState: правило react-hooks/exhaustive-deps их не требует, потому что они гарантированно стабильны.
Дальше стоит показать границу: функция вне компонента, которая читает изменяемую переменную модуля, уже не безопасна. Эффект не перезапустится, React о такой зависимости не знает, и вы получите результат, посчитанный по устаревшему значению.
Где спотыкаются
Отвечают, что зависимости нужны ради производительности, а добавление функции «нагружает приложение» или «течёт памятью». Ни того, ни другого нет: массив управляет ровно одним, моментом повторного запуска эффекта.
Второе: путают пустой массив и его отсутствие. useEffect(fn, []) выполняется после монтирования, useEffect(fn) без второго аргумента после каждого рендера. Ошибка встречается постоянно и даёт бесконечный цикл, если внутри вызывается установка состояния.
Третье: гасят предупреждение линтера комментарием вместо того, чтобы убрать зависимость по-настоящему. Функцию выносят из компонента, заворачивают в useCallback или прячут внутрь самого эффекта, а отключённое правило рано или поздно оставит эффект с устаревшими пропсами.