Последние два года я наблюдаю интересный тренд: React-комьюнити массово протрезвело от useEffect. После лет холиваров “классовые vs функциональные компоненты” мы наконец разобрались, что проблема не в парадигме, а в злоупотреблении side effects. На этом фоне выход eslint-plugin-react-you-might-not-need-an-effect v1.0.0 — отличный повод пересмотреть свои привычки.
Что не так с нашими эффектами
Проблема useEffect не в самом API, а в том, как мы его используем. Типичные кейсы, которые я встречаю в ревью:
- Эффекты-костыли для синхронизации состояния, которое можно выразить через композицию
- Подписки на внешние сторы через useEffect вместо useSyncExternalStore
- Каскады обновлений, когда один эффект триггерит другой, а тот — третий
Новый плагин ловит именно эти антипаттерны. Вот пример из его документации:
// ❌ До
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
const updateState = () => setIsOnline(navigator.onLine);
window.addEventListener('online', updateState);
window.addEventListener('offline', updateState);
return () => {
window.removeEventListener('online', updateState);
window.removeEventListener('offline', updateState);
};
}, []);
}
// ✅ После
function useOnlineStatus() {
return useSyncExternalStore(subscribe, getSnapshot);
}
Что изменилось в v1.0.0:
Новое правило для внешних сторов
Правило no-external-store-subscription закрывает последний пробел относительно официальной React-документации. Оно заставляет задуматься: действительно ли вам нужен эффект для работы с внешним состоянием? В 90% случаев ответ — нет.
Особенно радует, что плагин учитывает контекст:
- В компоненте предложит поднять состояние
- В кастомном хуке порекомендует вернуть значение
Меньше ложных срабатываний
Автор переработал детекцию переменных, что снизило количество false positives для:
- Результатов useQuery и аналогичных хуков
- Алиасов через деструктуризацию
- HOC-обёрток
На практике это значит, что теперь можно добавить плагин в legacy-проект без сотни исключений.
Технические улучшения
Миграция на TypeScript и сборку через tsdown — это не просто “мы тоже используем модный инструмент”. В данном случае это дало:
- Автоматическую работу с ESM/CJS
- Более точную типизацию для сложных AST-правил
- Упрощение процесса публикации
Лично для меня главный сюрприз — совместимость с Oxlint. Если вы ещё не пробовали этот Rust-аналог ESLint, теперь можно тестировать новые правила без полного перехода.
Где это имеет смысл
Плагин идеально впишется в:
- Новые проекты на React 18+
- Легаси-приложения с кучей эффектов
- Команды, которые хотят унифицировать подход к side effects
А вот где я бы пока воздержался:
- Проекты с классовыми компонентами (плагин заточен под хуки)
- Приложения, сильно завязанные на useEffect для работы с не-React API
Попробуйте добавить его с минимальным конфигом:
// eslintrc.js
module.exports = {
plugins: ['react-you-might-not-need-an-effect'],
rules: {
'react-you-might-not-need-an-effect/no-external-store-subscription': 'warn'
}
}
После недели использования вы удивитесь, сколько эффектов в вашем коде на самом деле лишние. Мой рекорд — 40% удалённых useEffect в одном из проектов без изменения функциональности.
Источник: https://github.com/nickjvandyke/eslint-plugin-react-you-might-not-need-an-effect