Що означає "state lifting" (підйом стану)?
Що таке "підйом стану" (state lifting)
State lifting - це перенесення (підйом) стану з дочірнього компонента в його батька, щоб кілька компонентів могли ділитися спільними даними або синхронізуватися між собою.
Приклад проблеми
Уяви, у нас є два поля вводу: одне - у градусах Цельсія, інше - у Фаренгейтах. Кожне зберігає свій локальний стан.
function CelsiusInput() {
const [celsius, setCelsius] = useState("");
return <input value={celsius} onChange={e => setCelsius(e.target.value)} />;
}
function FahrenheitInput() {
const [fahrenheit, setFahrenheit] = useState("");
return <input value={fahrenheit} onChange={e => setFahrenheit(e.target.value)} />;
}Проблема: Якщо користувач змінить Цельсій, Фаренгейт не оновиться. Два компоненти не синхронізовані, тому що в кожного свій стан.
Рішення - підняти стан вище (у батька)
Перенесемо спільний стан у батьківський компонент,
а дочірнім передамо його через props.
function TemperatureConverter() {
const [celsius, setCelsius] = useState("");
const fahrenheit = (celsius * 9) / 5 + 32;
return (
<div>
<CelsiusInput value={celsius} onChange={setCelsius} />
<FahrenheitDisplay value={fahrenheit} />
</div>
);
}
function CelsiusInput({ value, onChange }) {
return (
<input
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder="°C"
/>
);
}
function FahrenheitDisplay({ value }) {
return <p>{value} °F</p>;
}Тепер у нас одне джерело істини - celsius у батька,
і обидва компоненти синхронізовані.
Візуально
До lifting:
[Child1: has state] [Child2: has state] розсинхронізація
Після lifting:
[Parent: has state]
├── [Child1: отримує через props]
└── [Child2: отримує через props] синхронізованоКоли потрібен state lifting
Використовуй "підйом стану", коли:
- кілька компонентів залежать від одних і тих же даних;
- потрібно, щоб одна зміна впливала на інші;
- стан "належить" не тільки одному компоненту.
Приклад 1 - форма і передперегляд
function App() {
const [text, setText] = useState("");
return (
<>
<Input value={text} onChange={setText} />
<Preview text={text} />
</>
);
}text піднятий в App,
і тепер Input і Preview працюють з одними даними.
Приклад 2 - фільтрація і список
function App() {
const [filter, setFilter] = useState("");
const items = ["apple", "banana", "grape"];
const filtered = items.filter(item => item.includes(filter));
return (
<>
<Search value={filter} onChange={setFilter} />
<List items={filtered} />
</>
);
}Тепер зміна поля пошуку впливає на список.
Якби Search і List мали свої стани, вони б "жили окремо".
Відмінність від state colocation
| Концепція | Суть |
|---|---|
| State colocation | "Зберігай стан якомога ближче до місця використання." |
| State lifting | "Якщо стан потрібен кільком компонентам, підніми його туди, де вони перетинаються." |
Ідеально, коли ці принципи в рівновазі:
- стан не занадто високо (щоб не було зайвих ререндерів),
- але й не занадто низько (щоб не дублювати дані).
Помилки при підйомі стану
| Помилка | Чому погано |
|---|---|
| Підняв занадто високо | Викличе ререндер усіх дочірніх компонентів |
| Не підняв взагалі | Дані дублюються, розсинхронізація |
| Змінюєш стан з "не власника" | Порушує принцип односпрямованого потоку даних |
Практичний патерн
Якщо тобі потрібно "передати вгору" нове значення з дочірнього компонента,
використовуй callback (функцію з props):
function Child({ onChange }) {
return <input onChange={(e) => onChange(e.target.value)} />;
}Батько вирішує, що робити з новим значенням. Дочірній компонент просто "повідомляє про подію".
Підсумок
| Питання | Відповідь |
|---|---|
| Що таке state lifting? | Перенесення стану з дочірнього компонента в батька |
| Навіщо? | Щоб кілька компонентів могли синхронізуватися |
| Як реалізується? | Через props і callback-и |
| Коли потрібен? | Коли кілька компонентів залежать від одних даних |
| Як пов'язаний з colocation? | Піднімаємо лише настільки, наскільки потрібно, не вище |
| Головна мета | Одне "джерело істини" для пов'язаних компонентів |
Проста аналогія
Кожен компонент - це "кімната".
Коли два пристрої в різних кімнатах мають працювати з одним пультом, логічно підняти пульт нагору, у коридор, щоб ним могли користуватися обидва.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.