Состояние: useState
Состояние — это данные, которые компонент помнит между отрисовками: значение счётчика, текст в поле, открыто ли меню. Когда состояние меняется, React заново вызывает функцию компонента и обновляет страницу. Для состояния используют хук useState. Хук — это функция React, имя которой начинается с use; вызывают её внутри компонента.
Первый счётчик
Создайте src/components/Counter.jsx:
// src/components/Counter.jsx
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Нажатий: {count}</button>;
}Выведите <Counter /> в src/App.jsx. Кнопка покажет «Нажатий: 0», и с каждым кликом число будет расти.
Как это работает
useState(0) возвращает массив из двух элементов, который сразу раскладывают на переменные:
| Элемент | Что это |
|---|---|
count | Текущее значение, в первый раз — 0 |
setCount | Функция, которая задаёт новое значение и запускает перерисовку |
Порядок такой: клик вызывает setCount(1) → React снова вызывает Counter → useState возвращает уже 1 → на странице новый текст. Имена выбираете вы, принято писать пару something и setSomething.
Состояние в списке задач
Добавим кнопку, которая показывает и скрывает выполненные задачи. Измените src/App.jsx:
// src/App.jsx
import { useState } from 'react';
import TodoList from './components/TodoList.jsx';
const todos = [
{ id: 1, text: 'Купить молоко', done: false },
{ id: 2, text: 'Позвонить Олегу', done: true },
];
export default function App() {
const [showDone, setShowDone] = useState(true);
const visible = showDone ? todos : todos.filter((todo) => !todo.done);
return (
<>
<button onClick={() => setShowDone(!showDone)}>
{showDone ? 'Скрыть выполненные' : 'Показать выполненные'}
</button>
<TodoList todos={visible} />
</>
);
}Нажатие на кнопку прячет «Позвонить Олегу», повторное — возвращает её обратно. Текст кнопки меняется вместе с состоянием.
Обновление от предыдущего значения
Если новое значение зависит от старого, надёжнее передать в setCount функцию — она получит актуальное значение:
// src/components/Counter.jsx
function handleAddTwo() {
setCount((value) => value + 1);
setCount((value) => value + 1);
}Такой обработчик прибавит 2. Два вызова setCount(count + 1) подряд прибавили бы только 1: count внутри одного обработчика не меняется до следующей отрисовки.
Своё состояние у каждого экземпляра
Если вывести <Counter /> два раза, у каждой кнопки будет своё число: состояние принадлежит конкретному месту в дереве компонентов, а не функции.
Частая ошибка
Обычная переменная не подходит для состояния. Её изменение не вызывает перерисовку, а при следующей отрисовке она создаётся заново:
export default function Counter() {
let count = 0;
// Число на странице не изменится.
return <button onClick={() => count++}>Нажатий: {count}</button>;
}Всё, что должно меняться на экране, храните через useState и меняйте только функцией-сеттером.