Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що означає "state lifting" (підйом стану)?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**State lifting** - це перенесення (підйом) стану з дочірнього компонента в його батька, щоб кілька компонентів могли ділитися спільними даними або синхронізуватися між собою. **Ключове:** головна мета підйому стану - мати одне "джерело істини" для пов'язаних компонентів, піднімаючи стан лише настільки, наскільки потрібно, не вище.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке "підйом стану" (state lifting) > **State lifting** - це перенесення (підйом) стану з дочірнього компонента в його батька, > щоб кілька компонентів могли **ділитися спільними даними** або **синхронізуватися** між собою. --- ### Приклад проблеми Уяви, у нас є два поля вводу: одне - у градусах Цельсія, інше - у Фаренгейтах. Кожне зберігає свій локальний стан. ```javascript 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`. ```javascript 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` у батька, і обидва компоненти синхронізовані. --- ## Візуально ```javascript До lifting: [Child1: has state] [Child2: has state] розсинхронізація Після lifting: [Parent: has state] ├── [Child1: отримує через props] └── [Child2: отримує через props] синхронізовано ``` --- ## Коли потрібен state lifting Використовуй "підйом стану", коли: - кілька компонентів **залежать від одних і тих же даних**; - потрібно, щоб одна зміна впливала на інші; - стан "належить" **не тільки одному компоненту**. --- ### Приклад 1 - форма і передперегляд ```javascript function App() { const [text, setText] = useState(""); return ( <> <Input value={text} onChange={setText} /> <Preview text={text} /> </> ); } ``` `text` піднятий в `App`, і тепер `Input` і `Preview` працюють з одними даними. --- ### Приклад 2 - фільтрація і список ```javascript 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`): ```javascript function Child({ onChange }) { return <input onChange={(e) => onChange(e.target.value)} />; } ``` Батько вирішує, що робити з новим значенням. Дочірній компонент просто "повідомляє про подію". --- ## Підсумок | Питання | Відповідь | |---|---| | Що таке state lifting? | Перенесення стану з дочірнього компонента в батька | | Навіщо? | Щоб кілька компонентів могли синхронізуватися | | Як реалізується? | Через `props` і callback-и | | Коли потрібен? | Коли кілька компонентів залежать від одних даних | | Як пов'язаний з colocation? | Піднімаємо лише настільки, наскільки потрібно, не вище | | Головна мета | Одне "джерело істини" для пов'язаних компонентів | --- ## Проста аналогія > Кожен компонент - це "кімната". > > Коли два пристрої в різних кімнатах мають працювати з одним пультом, > логічно **підняти пульт нагору, у коридор**, > щоб ним могли користуватися обидва.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.