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

Как вызвать UseEffect один раз?

1.7 Middle🔥 211 комментариев
#React

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Вызов useEffect один раз при монтировании компонента

useEffect — это React хук, который позволяет выполнять побочные эффекты (side effects) в функциональных компонентах. Часто требуется выполнить код один раз при монтировании компонента, например для загрузки данных с сервера.

Использование пустого массива зависимостей

Чтобы вызвать useEffect только один раз при монтировании компонента, нужно передать пустой массив зависимостей []:

import { useEffect, useState } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    console.log('Компонент смонтирован!');
    // Код выполнится один раз
  }, []);

  return <div>{data}</div>;
}

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

Hook useEffect имеет параметр — массив зависимостей (dependency array). React сравнивает зависимости перед каждым рендером:

  • Без массива зависимостей: эффект выполняется после каждого рендера
  • Пустой массив []: эффект выполняется один раз после первого рендера
  • С зависимостями [dep1, dep2]: эффект выполняется, когда любая из зависимостей изменилась
// ❌ Выполнится при каждом рендере
useEffect(() => {
  console.log('После каждого рендера');
});

// ✅ Выполнится один раз при монтировании
useEffect(() => {
  console.log('При монтировании');
}, []);

// Выполнится при изменении userId
useEffect(() => {
  console.log('userId изменился:', userId);
}, [userId]);

Практический пример: загрузка данных

import { useEffect, useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchUser() {
      try {
        setLoading(true);
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchUser();
  }, []); // Зависит от пустого массива — загружается один раз при монтировании

  if (loading) return <div>Загрузка...</div>;
  if (error) return <div>Ошибка: {error}</div>;
  return <div>{user.name}</div>;
}

Очистка ресурсов (Cleanup function)

При размонтировании компонента часто требуется очистить ресурсы. Это делается через return функцию внутри useEffect:

useEffect(() => {
  console.log('Компонент смонтирован');

  // Cleanup функция — выполнится при размонтировании
  return () => {
    console.log('Компонент размонтирован');
    // Отписка от событий, отмена запросов, очистка памяти
  };
}, []);

Пример с подпиской на события

function WindowResize() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    function handleResize() {
      setWidth(window.innerWidth);
    }

    window.addEventListener('resize', handleResize);

    // Cleanup: отписаться при размонтировании
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // Один раз при монтировании

  return <div>Ширина: {width}px</div>;
}

Частая ошибка: зависит от userId

function UserProfile({ userId }) {
  useEffect(() => {
    // Если userId изменится, нужно перезагрузить данные
    fetchUser(userId);
  }, [userId]); // Добавляем userId в зависимости!
}

Сравнение подходов

МассивКогда выполняетсяИспользование
Не указанПосле каждого рендераРедко
[]Один раз при монтированииИнициализация, загрузка данных
[dep1, dep2]Когда изменился dep1 или dep2Реактивные эффекты

Резюме

Чтобы вызвать useEffect один раз при монтировании компонента, передайте пустой массив зависимостей []. Это основной паттерн для выполнения инициализационного кода, загрузки начальных данных с сервера и настройки подписок на события. Не забудьте про cleanup функцию, если нужно освобождать ресурсы при размонтировании.

Как вызвать UseEffect один раз? | PrepBro