JavaRush /Курсы /Модуль 3: React /Основы состояния компонента с useState — создание и управ...

Основы состояния компонента с useState — создание и управление состоянием

Модуль 3: React
1 уровень , 8 лекция
Открыта

Управление состоянием компонента

В React состояние управляет тем, как компоненты реагируют на пользовательские действия, данные и события. Это как бариста в кофейне — у него есть "состояние" (количество молока, наполненность кофейного бункера), которое меняется в зависимости от ваших заказов.

Состояние позволяет приложениям быть интерактивными, обновляя интерфейс, когда происходит что-то новое. Например:

  • Количество товаров в корзине.
  • Цвет кнопки, если вы навели на неё мышь.
  • Показ/скрытие выпадающего списка.

В React состояние всегда принадлежит компоненту и существует в рамках его жизненного цикла.

Что такое useState?

useState — это хук (функция), который позволяет функциональным компонентам в React иметь собственное состояние. До появления хуков в React 16.8 состояние можно было использовать только с классовыми компонентами. Теперь же функциональные компоненты стали настоящими рок-звёздами React-а.

Вот базовая структура:

import React, { useState } from 'react';

const Example = () => {
  const [state, setState] = useState(initialValue);
  return <div>{state}</div>;
};

useState возвращает массив из двух элементов:

  1. Текущее значение состояния (здесь — state).
  2. Функция для обновления состояния (здесь — setState).

Как создать состояние с useState?

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

import React, { useState } from 'react';

const Counter = () => {
  // Создаем состояние, начальное значение 0
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1); // Обновление состояния
  };

  return (
    <div>
      <p>Вы нажали {count} раз</p>
      <button onClick={handleClick}>Нажми меня</button>
    </div>
  );
};

export default Counter;

Здесь произошло вот что:

  1. Мы создали состояние count с начальным значением 0.
  2. Использовали setCount для обновления значения.
  3. На каждый клик вызывается handleClick, и счётчик увеличивается.

Особенности useState

  1. Асинхронность. Обновление состояния может быть асинхронным. Если вы пытаетесь обновить состояние в зависимости от его предыдущего значения, лучше использовать функцию:
    setCount((prevCount) => prevCount + 1);
    

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

  2. Разделение состояний. Каждый вызов useState создаёт отдельный "ячейку" состояния. Это позволяет разделять логику:
    const [likes, setLikes] = useState(0);
    const [comments, setComments] = useState([]);
    
  3. Начальное значение. useState принимает начальное значение состояния и может быть чем угодно: числом, строкой, массивом, объектом.

Пример: Состояние с объектом

Состояние может быть не только простым числом или строкой, но и более сложной структурой, например, объектом. Представим, что мы создаём форму, в которой пользователь может ввести имя и email.

import React, { useState } from 'react';

const Form = () => {
  const [formState, setFormState] = useState({ name: '', email: '' });

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = event.target;
    setFormState((prevState) => ({
      ...prevState, // Сохраняем предыдущие значения
      [name]: value, // Обновляем поле по имени
    }));
  };

  return (
    <form>
      <label>
        Имя:
        <input
          type="text"
          name="name"
          value={formState.name}
          onChange={handleChange}
        />
      </label>
      <label>
        Email:
        <input
          type="email"
          name="email"
          value={formState.email}
          onChange={handleChange}
        />
      </label>
      <p>
        Ваше имя: {formState.name}, ваш email: {formState.email}
      </p>
    </form>
  );
};

export default Form;

Здесь мы используем объект для хранения данных в форме. Используя спред-оператор ...prevState, мы сохраняем предыдущие значения и обновляем только нужное поле.

Что делать со сложными структурами данных?

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

Пример: добавление элемента в массив

const [items, setItems] = useState<string[]>([]);

const addItem = () => {
  setItems((prevItems) => [...prevItems, `Item ${prevItems.length + 1}`]);
};

Пример: удаление элемента из массива

const removeItem = (index: number) => {
  setItems((prevItems) => prevItems.filter((_, i) => i !== index));
};

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

Типизация состояния с useState

TypeScript автоматически выведет тип данных состояния из переданного значения. Но иногда вам нужно указать тип явно.

Пример: типизация строки

const [name, setName] = useState<string>('');

Пример: типизация массива

const [numbers, setNumbers] = useState<number[]>([]);

Пример: типизация объекта

interface User {
  name: string;
  age: number;
}

const [user, setUser] = useState<User>({ name: '', age: 0 });

Если вы заметили, мы используем интерфейсы для объектов. Это делает код более читаемым и безопасным.

Типичные ошибки при работе с useState

  1. Забыть использовать функцию обновления состояния. Если попытаетесь напрямую изменить состояние state = newValue, React будет игнорировать изменения.
  2. Мутация состояния. Если вы изменяете массив или объект без создания копии, React может не отобразить изменения. Всегда используйте методы .map, .filter, или спред-оператор.
  3. Неправильная обработка асинхронных обновлений. Если обновления зависят от предыдущего состояния, используйте функцию в setState.

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

Каждый React-разработчик сталкивается с задачами, где нужно запоминать и изменять данные. Использование useState — это основа взаимодействия с пользовательским интерфейсом. Например:

  • Управление формами (ввод текста, переключатели).
  • Создание интерактивных элементов (счётчики, переключатели тем).
  • Реализация простой логики (например, модальные окна).
// Итоговое мини-приложение: Управление темой
import React, { useState } from 'react';

const ThemeSwitcher = () => {
  const [isDarkMode, setIsDarkMode] = useState(false);

  const toggleTheme = () => {
    setIsDarkMode((prev) => !prev);
  };

  return (
    <div style={{ backgroundColor: isDarkMode ? '#333' : '#fff', color: isDarkMode ? '#fff' : '#000', padding: '20px' }}>
      <p>{isDarkMode ? 'Темная тема' : 'Светлая тема'}</p>
      <button onClick={toggleTheme}>Переключить тему</button>
</div>
);
};

export default ThemeSwitcher;

Поздравляю! Мы не просто меняем тему, мы обучаемся управлению состоянием на лету! Теперь вы готовы к ещё более сложным задачам. 😉

1
Задача
Модуль 3: React, 1 уровень, 8 лекция
Недоступна
Создание счётчика нажатий
Создание счётчика нажатий
1
Задача
Модуль 3: React, 1 уровень, 8 лекция
Недоступна
Управление видимостью текста
Управление видимостью текста
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ