← Назад к вопросам

Можно ли использовать хуки внутри условия?

2.2 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему нельзя использовать хуки внутри условий в React

Нет, использовать хуки React (такие как useState, useEffect, useContext и другие) внутри условий, циклов или вложенных функций категорически нельзя. Это фундаментальное правило, которое React строго требует соблюдать при работе с хуками. Нарушение этого правила приведёт к ошибке с сообщением "React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render." в консоли разработчика.

Основная причина: Гарантия порядка вызова хуков

React полагается на строгий и стабильный порядок вызова хуков между рендерами одного и того же компонента. Внутри React для каждого компонента ведётся внутренний список (или очередь) "ячеек памяти" (memory cells), которые хранят состояние хуков.

// ❌ НЕПРАВИЛЬНО: хук вызывается внутри условия
function MyComponent({ shouldUseCounter }) {
  if (shouldUseCounter) {
    const [count, setCount] = useState(0); // Хук может быть не вызван!
    // ...
  }
  const [name, setName] = useState('');   // Порядок нарушен
}

// ✅ ПРАВИЛЬНО: хуки всегда вызываются в одинаковом порядке
function MyComponent({ shouldUseCounter }) {
  const [count, setCount] = useState(0); // Всегда первым
  const [name, setName] = useState('');  // Всегда вторым

  const counterLogic = shouldUseCounter ? count : null;
  // ... или используйте другой хук
  const enabledState = useState(null);
  const stateToUse = shouldUseCounter ? count : enabledState[0];
}

На каждом рендере React проходит по этому списку ячеек по порядку. Если в одном рендере хук был вызван первым, а в следующем — вторым (из-за сработавшего условия if), React "перепутает" состояние между хуками. Например, значение useState для счётчика может быть ошибочно присвоено переменной имени, что приведёт к непредсказуемым багам и крашу приложения.

Как правильно организовать условную логику с хуками

Существует несколько паттернов, позволяющих соблюсти правило хуков, сохранив нужную функциональность:

1. Выносите условие ВНУТРЬ хука

Используйте условную логику внутри эффектов или других хуков, а не вокруг их вызова.

function MyComponent({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Условие внутри хука useEffect - правильно
    if (userId) {
      fetchUser(userId).then(setUser);
    }
  }, [userId]);
}

2. Разделяйте компоненты

Если логика сильно различается, разделите компонент на два, используя условный рендеринг на уровне выше.

function UserProfile({ user }) {
  return user ? <AuthenticatedView user={user} /> : <GuestView />;
}

function AuthenticatedView({ user }) {
  // Все хуки вызываются в стабильном порядке
  const [settings, setSettings] = useState(null);
  useEffect(() => { /* ... */ }, [user.id]);
  return <div>Hello, {user.name}</div>;
}

function GuestView() {
  const [guestId, setGuestId] = useState(generateId());
  return <div>Welcome, guest #{guestId}</div>;
}

3. Используйте хук useMemo или useCallback для условных вычислений

Для условной зависимости мемоизированных значений или функций применяйте хуки до условия, а логику размещайте внутри них.

function MyComponent({ heavyData, isEnabled }) {
  // Хук useMemo вызывается всегда
  const processedData = useMemo(() => {
    // Условие внутри useMemo
    return isEnabled ? expensiveTransform(heavyData) : null;
  }, [heavyData, isEnabled]); // Зависимости включают условие
}

Исключение из правила: Пользовательские хуки

Пользовательские хуки (custom hooks) также должны соблюдать это правило. Однако вы можете использовать условия внутри тела пользовательского хука, если сами вызовы хуков React внутри него остаются в неизменном порядке.

// ✅ ПРАВИЛЬНО: внутри кастомного хука условная логика допустима,
// если порядок встроенных хуков не нарушен
function useCustomHook(shouldFetch) {
  const [data, setData] = useState(null);
  // Условие НЕ вокруг useState или useEffect
  useEffect(() => {
    if (shouldFetch) { // Условие внутри хука - нормально
      fetchData().then(setData);
    }
  }, [shouldFetch]);
  return data;
}

Что происходит технически при нарушении?

React использует индекс текущего обрабатываемого хука, который увеличивается с каждым вызовом хука в компоненте. При сбое порядка React не сможет сопоставить текущий вызов с правильной ячейкой памяти, что ведёт к:

  • Смешиванию состояний разных хуков.
  • Потере актуального значения состояния.
  • Ошибкам выполнения в последующих рендерах.

Вывод

Правило "Не вызывайте хуки внутри условий" — это не просто рекомендация по стилю, а критическое требование для корректной работы механизма состояния и жизненного цикла React. Соблюдение этого правила гарантирует, что React сможет однозначно связать каждый вызов хука с конкретной ячейкой памяти между рендерами. Всегда используйте альтернативные подходы: условия внутри хуков, разделение компонентов или условный рендеринг, чтобы ваше приложение оставалось стабильным и предсказуемым.

Можно ли использовать хуки внутри условия? | PrepBro