Что такое state и как его использовать?react-8

Определение state

State — это внутренние данные компонента, которые могут изменяться со временем и влиять на его отображение. В отличие от props, state полностью контролируется самим компонентом.

Ключевые характеристики:

  • Локальность: Принадлежит конкретному компоненту
  • Изменяемость: Может обновляться (в отличие от props)
  • Асинхронность: Обновления state могут происходить не мгновенно
  • Триггер ререндера: Изменение state вызывает повторный рендеринг компонента

Основные способы работы с state

1. Использование хука useState

import { useState } from 'react';

function Counter() {
  // Объявление state: count - текущее значение, setCount - функция обновления
  const [count, setCount] = useState(0); // Начальное значение 0

  return (
    <div>
      <p>Вы кликнули {count} раз</p>
      <button onClick={() => setCount(count + 1)}>
        Кликни меня
      </button>
    </div>
  );
}

2. Использование this.state

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 }; // Инициализация state
  }

  render() {
    return (
      <div>
        <p>Вы кликнули {this.state.count} раз</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Кликни меня
        </button>
      </div>
    );
  }
}

Правила работы с state

1. Не изменяйте state напрямую

Неправильно:

// Для функциональных компонентов
count = count + 1;
// Для классовых компонентов
this.state.count = 5;

Правильно:

// Функциональные компоненты
setCount(count + 1);
// Классовые компоненты
this.setState({ count: 5 });

2. Используйте функциональную форму при зависимости от предыдущего state

setCount(prevCount => prevCount + 1);
// Для классовых компонентов
this.setState(prevState => ({ count: prevState.count + 1 }));

3. Объединяйте связанные данные в один объект state

const [user, setUser] = useState({
  name: 'Иван',
  age: 30,
  isActive: true
});

// Обновление
setUser(prev => ({ ...prev, age: 31 }));

Продвинутые сценарии работы с state

1. Ленивая инициализация state

const [data, setData] = useState(() => {
  // Выполняется только при первоначальном рендере
  const initialData = computeExpensiveValue();
  return initialData;
});

2. Работа с сложным state

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <button onClick={() => dispatch({ type: 'increment' })}>
      Count: {state.count}
    </button>
  );
}

3. Подъем state

Когда несколько компонентов должны использовать одни данные:

function Parent() {
  const [sharedState, setSharedState] = useState('');

  return (
    <>
      <ChildA value={sharedState} onChange={setSharedState} />
      <ChildB value={sharedState} />
    </>
  );
}

Оптимизация работы с state

1. Мемоизация вычислений

const expensiveValue = useMemo(() => computeExpensiveValue(count), [count]);

2. Избегание лишних ререндеров

const MemoizedComponent = React.memo(function MyComponent({ prop }) {
  // Рендерится только при изменении prop
});

Резюмируем

  1. State — это:

    • Внутренние изменяемые данные компонента
    • Локальное хранилище информации
    • Триггер ререндера при изменении
  2. Основные методы работы:

    • useState для функциональных компонентов
    • this.state и this.setState для классовых компонентов
    • useReducer для сложной логики обновлений
  3. Главные правила:

    • Не изменяйте state напрямую
    • Используйте функциональные обновления при зависимости от предыдущего состояния
    • Поднимайте state при необходимости общего доступа
  4. Оптимизации:

    • Мемоизация ресурсоемких вычислений
    • Избегание лишних ререндеров
    • Правильное структурирование данных state

Совет: Для глобального состояния приложения рассмотрите использование Context API или специализированных решений (Redux, MobX, Zustand), когда state нужно разделять между многими компонентами.