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

Как затриггерить useEffect?

1.0 Junior🔥 131 комментариев
#React

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

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

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

Что такое useEffect

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

Базовый синтаксис

useEffect(() => {
  // Код, который выполняется ПОСЛЕ каждого рендера
  console.log('Компонент отрендерился');
});

Код внутри useEffect выполняется ПОСЛЕ того, как компонент отрисован на экране.

Способы затриггерить useEffect

1. Без массива зависимостей (выполняется после каждого рендера)

function Component() {
  useEffect(() => {
    console.log('Выполняется после КАЖДОГО рендера!');
  });

  return <div>Hello</div>;
}

Этот вариант может привести к бесконечным циклам, обычно избегают.

2. С пустым массивом зависимостей (выполняется только при монтировании)

function Component() {
  useEffect(() => {
    console.log('Выполняется ОДИН РАЗ при монтировании компонента');
    
    return () => {
      console.log('Очистка при размонтировании');
    };
  }, []);

  return <div>Hello</div>;
}

Самый распространённый вариант для загрузки данных при инициализации.

3. С массивом зависимостей (выполняется при изменении зависимостей)

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

  useEffect(() => {
    console.log(`Загружаем пользователя ${userId}`);
    
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => setUser(data));
  }, [userId]);

  return <div>{user?.name}</div>;
}

Эффект запускается при изменении userId.

Практические примеры

Загрузка данных

function PostList() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchPosts = async () => {
      try {
        const response = await fetch('/api/posts');
        const data = await response.json();
        setPosts(data);
      } catch (error) {
        console.error('Ошибка загрузки:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchPosts();
  }, []);

  if (loading) return <div>Загрузка...</div>;
  return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}

Подписка на событие

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

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    
    window.addEventListener('resize', handleResize);
    
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

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

Следование за переменной

function SearchUsers({ searchTerm }) {
  const [results, setResults] = useState([]);

  useEffect(() => {
    if (!searchTerm) {
      setResults([]);
      return;
    }

    const timer = setTimeout(() => {
      fetch(`/api/search?q=${searchTerm}`)
        .then(res => res.json())
        .then(data => setResults(data));
    }, 300);

    return () => clearTimeout(timer);
  }, [searchTerm]);

  return <ul>{results.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

Множественные зависимости

function Chart({ userId, year, month }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(`/api/stats/${userId}/${year}/${month}`)
      .then(res => res.json())
      .then(data => setData(data));
  }, [userId, year, month]);

  return <div>{data && <ChartComponent data={data} />}</div>;
}

Распространённые ошибки

Забытая зависимость (infinite loop)

function BadComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(count + 1);
  }, []);
}

function GoodComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(c => c + 1);
  }, []);
}

Лишние пересчёты

function BadComponent() {
  const options = { page: 1 };
  
  useEffect(() => {
    fetch('/api/data', options);
  }, [options]);
}

function GoodComponent() {
  useEffect(() => {
    fetch('/api/data', { page: 1 });
  }, []);
}

Выводы

useEffect срабатывает ПОСЛЕ рендера компонента. Массив зависимостей контролирует, когда срабатит эффект: пустой массив [] означает срабатит один раз при монтировании (самый частый вариант), массив с зависимостями [dep1, dep2] срабатит при их изменении. Функция очистки в return удалит слушатели и таймеры при размонтировании. Правильный массив зависимостей критичен для избежания бесконечных циклов и утечек памяти.

Как затриггерить useEffect? | PrepBro