React: хуки и lifecycle

React предоставляет два основных подхода для управления состоянием и жизненным циклом компонентов: классовые компоненты с методами жизненного цикла и функциональные компоненты с хуками. Хуки позволяют функциональным компонентам использовать состояния и эффекты без необходимости писать классы.


useState

Хук useState предназначен для хранения и обновления состояния компонента.

import { useState } from 'react';

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

  const increment = () => setCount(prev => prev + 1);

  return (
    <div>
      <p>Счётчик: {count}</p>
      <button onCl ick={increment}>Увеличить</button>
    </div>
  );
}
  • useState(initialValue) возвращает массив из двух элементов: текущее значение состояния и функцию для его обновления.
  • Изменение состояния через setCount инициирует перерендеринг компонента, что позволяет интерфейсу синхронизироваться с данными.

useEffect

Хук useEffect используется для управления побочными эффектами и замещает большинство методов жизненного цикла классовых компонентов.

import { useState, useEffect } from 'react';

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

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

    return () => clearInterval(interval); // Очистка при размонтировании
  }, []); // Пустой массив зависимостей — эффект выполняется один раз
}
  • Массив зависимостей определяет, когда эффект будет выполняться. Пустой массив [] имитирует componentDidMount.
  • Функция очистки в useEffect заменяет componentWillUnmount.

Другие важные хуки

useRef

Используется для хранения мутабельных значений, которые не вызывают перерендеринг, или для доступа к DOM-элементам.

import { useRef } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  const focus = () => inputRef.current.focus();

  return <input ref={inputRef} type="text" />;
}
  • useRef сохраняет значение между рендерами.
  • Не триггерит повторный рендер при изменении ref.current.

useMemo и useCallback

useMemo кэширует результат вычислений, а useCallback кэширует функцию, предотвращая её пересоздание на каждом рендере.

import { useMemo, useCallback } from 'react';

const computedValue = useMemo(() => expensiveComputation(data), [data]);
const memoizedCallback = useCallback(() => doSomething(param), [param]);
  • Эти хуки особенно полезны при работе с большими компонентами и сложными вычислениями.

Жизненный цикл в классовых компонентах

Классические методы жизненного цикла:

  • componentDidMount() — вызывается после монтирования компонента.
  • componentDidUpdate(prevProps, prevState) — вызывается после обновления состояния или пропсов.
  • componentWillUnmount() — вызывается перед удалением компонента.
class Timer extends React.Component {
  state = { seconds: 0 };

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState(prev => ({ seconds: prev.seconds + 1 }));
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <p>Секунды: {this.state.seconds}</p>;
  }
}
  • Управление таймерами, подписками на события и сторонними библиотеками часто выполняется в этих методах.

Сравнение хуков и методов жизненного цикла

Особенность Классы Хуки
Состояние this.state + this.setState useState
Побочные эффекты componentDidMount, componentDidUpdate useEffect
Доступ к DOM createRef useRef
Переиспользование логики HOC или Render Props Пользовательские хуки
  • Хуки позволяют компоновку логики без иерархий классов, что делает код более читаемым и переиспользуемым.
  • Эффекты можно разделять на несколько useEffect, каждый из которых отвечает за конкретную задачу.

Практические рекомендации

  • Использовать хуки для новых компонентов, так как они проще и гибче.
  • Разделять эффекты по назначению, чтобы избежать смешивания логики в одном useEffect.
  • Хранить мутабельные значения через useRef вместо состояния, если не требуется ререндер.
  • Для сложных вычислений применять useMemo и useCallback для оптимизации производительности.

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