useState и useEffect

useState: управление состоянием компонентов

useState — это хук, предоставляемый React, который позволяет функциональным компонентам хранить и управлять локальным состоянием. До появления хуков для работы с состоянием приходилось использовать классовые компоненты и this.state, что усложняло код и снижало его читаемость. useState делает функциональные компоненты полноценной альтернативой классам.

Синтаксис и базовое использование:

import { useState } from 'react';

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

  return (
    <div>
      <p>Счётчик: {count}</p>
      <button onCl ick={() => setCount(count + 1)}>Увеличить</button>
    </div>
  );
}
  • count — текущее состояние.
  • setCount — функция для обновления состояния.
  • useState(0) — инициализация состояния значением 0.

Ключевые особенности useState:

  1. Множественные состояния: Один компонент может использовать несколько вызовов useState для хранения различных данных.
const [name, setName] = useState('Иван');
const [age, setAge] = useState(25);
  1. Ленивая инициализация: Если начальное значение требует вычислений, можно передать функцию.
const [expensiveValue, setExpensiveValue] = useState(() => computeExpensiveValue());
  1. Обновление состояния на основе предыдущего значения: Для безопасного изменения состояния используют колбэк.
setCount(prevCount => prevCount + 1);
  1. Примитивные и сложные типы: Состояние может быть числом, строкой, массивом, объектом или любым другим типом данных. Для объектов и массивов важно помнить о неизменяемости, создавая новый объект или массив при обновлении.
const [user, setUser] = useState({ name: 'Иван', age: 25 });
setUser(prev => ({ ...prev, age: prev.age + 1 }));

useEffect: побочные эффекты

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

Синтаксис и базовое использование:

import { useEffect, useState } from 'react';

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

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);
  
  return <p>Прошло секунд: {seconds}</p>;
}
  • Первый аргумент — функция эффекта, которая выполняется после рендера.
  • Второй аргумент — массив зависимостей (dependency array), определяющий, когда эффект будет вызываться.
  • Функция, возвращаемая из эффекта, используется для очистки ресурсов (аналог componentWillUnmount в классах).

Основные сценарии использования useEffect:

  1. Эффект без зависимостей:
useEffect(() => {
  console.log('Выполняется после каждого рендера');
});
  1. Эффект с пустым массивом зависимостей:
useEffect(() => {
  console.log('Выполняется один раз при монтировании');
}, []);
  1. Эффект с зависимостями:
useEffect(() => {
  console.log(`Состояние count изменилось: ${count}`);
}, [count]);
  1. Очистка ресурсов:
useEffect(() => {
  const handler = () => console.log('Событие');
  window.addEventListener('resize', handler);
  
  return () => window.removeEventListener('resize', handler);
}, []);

Взаимодействие useState и useEffect

Комбинация этих хуков позволяет синхронизировать состояние и побочные эффекты:

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

  useEffect(() => {
    async function load() {
      const response = await fetch('https://api.example.com/data');
      const result = await response.json();
      setData(result);
    }
    load();
  }, []);

  return <div>{data ? data.name : 'Загрузка...'}</div>;
}
  • Состояние data обновляется через setData.
  • Эффект выполняется один раз при монтировании компонента.
  • Обновление состояния вызывает повторный рендер, но эффект с пустым массивом зависимостей не будет повторно выполняться.

Рекомендации по использованию

  • Хранить локальные данные компонента в useState.
  • Выполнять асинхронные операции, подписки и очистку ресурсов через useEffect.
  • Минимизировать зависимости эффектов, избегая лишних рендеров.
  • При работе с объектами и массивами всегда создавать новые копии для обновления состояния.

Заключение по сути

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