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

В чем разница между useEffect и useCallback?

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

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

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

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

Разница между useEffect и useCallback

Это два разных хука React с разными целями. Часто их путают, но они решают разные проблемы.

useEffect

Назначение: запуск побочных эффектов при изменении зависимостей.

Побочные эффекты — это операции, которые взаимодействуют с внешним миром:

  • API запросы
  • Подписки на события
  • Работа с DOM
  • Таймеры
import { useState, useEffect } from "react";

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

  // Запускается когда userId изменится
  useEffect(() => {
    setLoading(true);
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });
  }, [userId]); // Массив зависимостей

  return <div>{loading ? "Загрузка..." : user.name}</div>;
}

Синтаксис:

useEffect(() => {
  // Код побочного эффекта
  
  return () => {
    // Очистка (cleanup) — опционально
  };
}, [dependencies]); // Зависимости

useCallback

Назначение: мемоизировать функцию, чтобы она не пересоздавалась на каждый рендер.

Это нужно для оптимизации производительности, когда функция передаётся в дочерние компоненты.

import { useCallback, useState } from "react";

export function List() {
  const [items, setItems] = useState([]);

  // Функция пересоздаётся только когда items изменится
  const addItem = useCallback((newItem) => {
    setItems([...items, newItem]);
  }, [items]); // Зависимости

  return <ListChild onAddItem={addItem} />;
}

Синтаксис:

const memoizedCallback = useCallback(() => {
  // Код функции
}, [dependencies]);

Прямое сравнение

АспектuseEffectuseCallback
ЦельЗапуск побочных эффектовМемоизация функции
Возвращаетundefinedфункцию
ЗапускаетсяПосле рендераНа каждый рендер, но возвращает мемоизированную функцию
CleanupПоддерживаетНет
ИспользованиеAPI, подписки, DOMПередача функции в props

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

Пример 1: Разница в поведении

import { useState, useEffect, useCallback } from "react";

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

  // useEffect запускается ПОСЛЕ рендера
  useEffect(() => {
    console.log("Компонент отрендерился, count=", count);
  }, [count]);

  // useCallback мемоизирует функцию
  const handleClick = useCallback(() => {
    console.log("Клик, count=", count);
  }, [count]);

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={handleClick}>Log Count</button>
    </>
  );
}

Пример 2: Когда нужен useCallback

import { useCallback } from "react";
import { ChildComponent } from "./ChildComponent";

export function Parent() {
  // БЕЗ useCallback — функция пересоздаётся на каждый рендер
  // это заставит Child перерендериться даже если props не изменились
  const handleSubmit = useCallback((data) => {
    console.log("Form submitted:", data);
  }, []);

  return <ChildComponent onSubmit={handleSubmit} />;
}

Пример 3: Очистка в useEffect

import { useEffect, useState } from "react";

export function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    // Код эффекта
    const interval = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);

    // Cleanup функция — очищает интервал
    return () => clearInterval(interval);
  }, []); // Пустой массив = эффект только один раз

  return <div>Seconds: {seconds}</div>;
}

Правила использования

useEffect:

  1. Используй для всех побочных эффектов
  2. Правильно указывай зависимости
  3. Помни про cleanup функцию для отписок/очистки
  4. Не создавай бесконечные циклы

useCallback:

  1. Используй когда передаёшь функцию в React.memo компонент
  2. Используй для оптимизации в больших списках
  3. Не переусложняй — сначала напиши без мемоизации
  4. Помни про зависимости

Заключение

  • useEffect = "делай что-то когда данные изменяются"
  • useCallback = "помни мою функцию, чтобы не пересоздавать её"

Они часто используются вместе: useCallback для функции, которая передаётся, и useEffect для выполнения побочных эффектов при её изменении.