Cover Image for Именуйте функции в useEffect: практика для читаемого кода в React

Именуйте функции в useEffect: практика для читаемого кода в React

15 апреля 2026

useEffect — один из основных хуков в React для работы с побочными эффектами. Но на практике код с несколькими эффектами часто становится трудночитаемым. Разработчик Neciu Dan предлагает простое решение: давать функциям внутри useEffect осмысленные имена.

Имена функция — это вопрос читаемости и понятности

  • Читаемость. Код становится самодокументируемым — название функции объясняет её назначение.
  • Отладка. В стеке ошибок отображается имя функции, проще найти проблемный эффект.
  • Рефакторинг. Сложный эффект легче вынести в кастомный хук, так как функция уже обособлена.
  • Командная работа. Коллегам не нужно вникать в детали реализации, чтобы понять логику компонента.

Пример из практики

Компонент должен:

  • загружать список продуктов при смене категории;
  • подписываться на обновления выбранного продукта;
  • логировать аналитические события.

Без названия

Функция внутри остаётся анонимной. В компоненте с несколькими эффектами приходится изучать тело каждой функции, чтобы понять её назначение. Это замедляет отладку и код-ревью.

function InventorySync({ warehouseId, locationId, onStockChange }) {
  const [stock, setStock] = useState<StockLevel[]>([]);
  const [connected, setConnected] = useState(false);
  const prevLocationId = useRef(locationId);

  useEffect(() => {
    const ws = new WebSocket(`wss://inventory.api/ws/${warehouseId}`);
    ws.onopen = () => setConnected(true);
    ws.onclose = () => setConnected(false);
    ws.onmessage = (event) => {
      const update = JSON.parse(event.data);
      setStock(prev => prev.map(s =>
        s.sku === update.sku ? { ...s, quantity: update.quantity } : s
      ));
    };
    return () => ws.close();
  }, [warehouseId]);

  useEffect(() => {
    if (!connected) return;
    fetch(`/api/warehouses/${warehouseId}/stock?location=${locationId}`)
      .then(res => res.json())
      .then(setStock);
  }, [warehouseId, locationId, connected]);

  useEffect(() => {
    if (prevLocationId.current !== locationId) {
      setStock([]);
      prevLocationId.current = locationId;
    }
  }, [locationId]);

  useEffect(() => {
    if (stock.length > 0) {
      onStockChange(stock);
    }
  }, [stock, onStockChange]);

  // ... render
}

С названием

Название функции сразу объясняет, что делает эффект.

function InventorySync({ warehouseId, locationId, onStockChange }) {
  const [stock, setStock] = useState<StockLevel[]>([]);
  const [connected, setConnected] = useState(false);
  const prevLocationId = useRef(locationId);

  useEffect(function connectToInventoryWebSocket() {
    const ws = new WebSocket(`wss://inventory.api/ws/${warehouseId}`);
    ws.onopen = () => setConnected(true);
    ws.onclose = () => setConnected(false);
    ws.onmessage = (event) => {
      const update = JSON.parse(event.data);
      setStock(prev => prev.map(s =>
        s.sku === update.sku ? { ...s, quantity: update.quantity } : s
      ));
    };
    return () => ws.close();
  }, [warehouseId]);

  useEffect(function fetchInitialStock() {
    if (!connected) return;
    fetch(`/api/warehouses/${warehouseId}/stock?location=${locationId}`)
      .then(res => res.json())
      .then(setStock);
  }, [warehouseId, locationId, connected]);

  useEffect(function resetStockOnLocationChange() {
    if (prevLocationId.current !== locationId) {
      setStock([]);
      prevLocationId.current = locationId;
    }
  }, [locationId]);

  useEffect(function notifyParentOfStockUpdate() {
    if (stock.length > 0) {
      onStockChange(stock);
    }
  }, [stock, onStockChange]);

  // ... render
}

Этот вариант проще читать при навигации по файлу компонента.

Когда применять паттерн

Именование эффектов имеет смысл, если:

  • логика эффекта занимает больше нескольких строк;
  • в компоненте несколько useEffect;
  • назначение эффекта неочевидно из зависимостей.

Для простых эффектов (например, обновление заголовка документа по одной переменной) выгода может быть минимальной. Но в реальных проектах именованные эффекты окупаются.

Итог

Именование функций в useEffect — практика с минимальными затратами и заметным эффектом. Она соответствует принципу «код пишут для людей, а не для компьютеров». Компоненты становятся проще для чтения, отладки и поддержки.


Источник: блог-пост Neciu Dan «Start naming your useEffect functions, you will thank me later».