- Главная
- Javascript
- Props и State — как React управляет данными
Props и State — как React управляет данными
Содержание
- Введение: данные в React
- Props — свойства компонента
- Props — только для чтения
- Значения по умолчанию для props
- State — внутреннее состояние компонента
- Хук useState — главный инструмент для state
- Обновление state (два способа)
- Состояния разных типов
- Обновление объектов и массивов в state
- Подъём состояния (Lifting State Up)
- Отличие Props от State
- Итог (что мы узнали)
- Задание для закрепления (на 7–10 минут)
- Что дальше?
Цель урока: понять два главных механизма работы с данными в React: Props (данные передаются сверху вниз, readonly) и State (данные живут внутри компонента, изменяемы). Научиться передавать данные между компонентами и управлять динамическим интерфейсом.
Введение: данные в React
Два главных инструмента для данных:
| Концепция | Что это | Можно изменять? | Откуда берётся? |
|---|---|---|---|
| Props | Параметры компонента | ❌ Нет (readonly) | Передаются от родителя |
| State | Внутреннее состояние | ✅ Да (через setState) |
Живёт внутри компонента |
Главная мысль:
- Props— это входные данные компонента (как аргументы функции).
- State — это внутренняя память компонента (как переменные внутри функции).
Props — свойства компонента
Props (сокращение от «properties») — это данные, которые родительский компонент передаёт дочернему.
Передача props:
function App() {
return (
<UserCard
name="Алексей"
age={25}
city="Москва"
isActive={true}
/>
);
}
Получение props в компоненте:
function UserCard(props) {
return (
<div>
<h2>{props.name}</h2>
<p>Возраст: {props.age}</p>
<p>Город: {props.city}</p>
<p>Статус: {props.isActive ? 'Активен' : 'Не активен'}</p>
</div>
);
}
Деструктуризация props (лучший способ):
function UserCard({ name, age, city, isActive }) {
return (
<div>
<h2>{name}</h2>
<p>Возраст: {age}</p>
<p>Город: {city}</p>
<p>Статус: {isActive ? 'Активен' : 'Не активен'}</p>
</div>
);
}
Props — только для чтения
Важнейшее правило React
Props нельзя изменять внутри компонента.
❌ Неправильно (ошибка):
function UserCard({ name }) {
name = "Иван"; // ОШИБКА! Нельзя менять props
return <h2>{name}</h2>;
}
✅ Правильно (props только читаем):
function UserCard({ name }) {
const displayName = name.toUpperCase(); // Можно использовать, но не менять
return <h2>{displayName}</h2>;
}
Почему так?
- Props — это аргументы функции
- Функция не должна менять свои аргументы (чистота функций)
- React должен предсказуемо работать
Значения по умолчанию для props
Можно задать значения по умолчанию, если prop не передан:
Способ 1. Через defaultProps (классовый стиль):
function UserCard({ name, age, city }) {
return <div>{name}, {age}, {city}</div>;
}
UserCard.defaultProps = {
name: 'Гость',
age: 0,
city: 'Неизвестно'
};
Способ 2. Через деструктуризацию (рекомендуется):
function UserCard({ name = 'Гость', age = 0, city = 'Неизвестно' }) {
return <div>{name}, {age}, {city}</div>;
}
Оживи свой сайт. Освой JavaScript!
Статичная верстка — это только скелет. Наш онлайн-курс "JavaScript с нуля до профи" даст твоим страницам мышцы и нервы. Научись создавать слайдеры, формы, интерактивные карты и получать данные с сервера.
От теории — к реальным скриптам в твоём портфолио.
State — внутреннее состояние компонента
State — это данные, которые компонент хранит сам в себе и может изменять. Когда state меняется, компонент перерисовывается.
Как работает state
- Ты объявляешь state с начальным значением
- React запоминает это значение
- Когда ты вызываешь функцию обновления, React изменяет значение и перерисовывает компонент
- Компонент видит новое значение state
Хук useState — главный инструмент для state
Синтаксис:
const [state, setState] = useState(initialValue);
Разбор:
- state — текущее значение (например,
count) - setState — функция для обновления (например,
setCount) - initialValue — начальное значение (например,
0)
Простейший пример (счётчик):
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // начальное значение 0
const increment = () => {
setCount(count + 1); // увеличиваем на 1
};
return (
<div>
<button onClick={increment}>Счёт: {count}</button>
</div>
);
}
На экране: При клике на кнопку число увеличивается на 1.
Пример реализации показан ниже.
Обновление state (два способа)
Способ 1. Прямое обновление (если новое значение не зависит от старого):
setCount(5); // всегда устанавливаем 5
setName('Иван'); // всегда устанавливаем 'Иван'
Способ 2. Обновление через функцию (если зависит от старого значения):
setCount(prevCount => prevCount + 1); // безопасно для асинхронности
setCount(prevCount => prevCount * 2);
Когда использовать второй способ?
- Когда новое значение зависит от старого
- Когда обновление может быть асинхронным (много вызовов подряд)
- Всегда, если есть сомнения
Пример с асинхронностью:
// ❌ Может не сработать правильно
setCount(count + 1);
setCount(count + 1); // Может прибавить только 1, а не 2
// ✅ Всегда сработает правильно
setCount(prev => prev + 1);
setCount(prev => prev + 1); // Прибавит 2
Состояния разных типов
Строка:
const [name, setName] = useState('Алексей');
Число:
const [age, setAge] = useState(25);
Булево (true/false):
const [isActive, setIsActive] = useState(true);
Массив:
const [items, setItems] = useState(['Яблоко', 'Банан']);
Объект:
const [user, setUser] = useState({ name: 'Алексей', age: 25 });
Обновление объектов и массивов в state
Важно: State нельзя менять напрямую! Нужно создавать новый объект/массив.
❌ Неправильно:
user.name = 'Иван'; // ОШИБКА! Мутация объекта
setUser(user);
✅ Правильно (объект):
setUser({ ...user, name: 'Иван' }); // Создаём новый объект
✅ Правильно (массив):
setItems([...items, 'Апельсин']); // Добавляем в конец
setItems(items.filter(item => item !== 'Банан')); // Удаляем
Подъём состояния (Lifting State Up)
Если несколько компонентов используют одни и те же данные, state нужно «поднять» к их общему родителю.
Проблема: Два компонента не могут иметь общий state напрямую.
Решение: state живёт в родителе, а дочерние компоненты получают его через props.
Пример:
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<ChildA count={count} />
<ChildB setCount={setCount} />
</div>
);
}
function ChildA({ count }) {
return <p>Счёт: {count}</p>;
}
function ChildB({ setCount }) {
return <button onClick={() => setCount(prev => prev + 1)}>+1</button>;
}
Важно: Теперь оба компонента работают с одним состоянием.
Отличие Props от State
| Характеристика | Props | State |
|---|---|---|
| Кто владеет | Родительский компонент | Сам компонент |
| Можно изменять? | ❌ Нет (readonly) | ✅ Да (через setState) |
| Передаётся ли вниз? | Да | Да, как props |
| Вызывает перерисовку? | Да (если изменился в родителе) | Да (при вызове setState) |
| Для чего используется | Передача данных | Хранение динамических данных |
Итог (что мы узнали)
| Что узнали | Как это работает |
|---|---|
| Props — входные данные | Передаются от родителя, только для чтения |
| State — внутреннее состояние | Живёт в компоненте, можно изменять |
| useState | Хук для создания state |
| Обновление state | Через сеттер, лучше через функцию |
| Не изменять напрямую | Всегда создавать новый объект/массив |
| Подъём состояния | Общий state у родителя |
Задание для закрепления (на 7–10 минут)
- Создай компонент
Counterс statecount(начальное значение0) - Добавь две кнопки: «+1», «-1» и «Сбросить»
- Создай компонент
Display, который принимаетcountчерез props и выводит текст:Текущее значение: {count} - В
App.jsxобъедини оба компонента:Counterкак родитель,Displayкак дочерний
Дополнительно: Добавь проверку, чтобы счёт не уходил в минус (при клике на «-1» не давать уйти ниже 0).
Проверка: Должен работать счётчик, который показывает число и не позволяет стать отрицательным. У вас должно получиться что-то похожее на показанное ниже.
Что дальше?
В следующем уроке разберём Conditional Rendering — как показывать разные элементы в зависимости от условий. Ты научишься делать интерфейсы, которые адаптируются под состояние приложения: показывать загрузку, сообщения об ошибках, переключать темы и многое другое. Это сделает твои приложения живыми и отзывчивыми.