Плаский стан (flat state)
Що означає "плаский стан"
Плаский стан (flat state) - це коли дані в useState (або useReducer)
не вкладені глибоко в об'єкти,
а зберігаються "на одному рівні".
Приклад: замість громіздкої структури
{
user: {
profile: {
name: "Tim",
age: 25
},
settings: {
theme: "dark"
}
}
}краще зберігати стан пласко:
{
userName: "Tim",
userAge: 25,
userTheme: "dark"
}або, якщо потрібно зберігати пов'язані дані, використовувати окремі стани:
const [profile, setProfile] = useState({ name: "Tim", age: 25 });
const [theme, setTheme] = useState("dark");Чому React любить "пласкі" стани
React перемальовує компонент щоразу, коли стан оновлюється, і важливо, щоб оновлення були локальними і простими.
Глибоко вкладені структури ламають цю простоту.
Проблема 1: складно оновлювати вкладені дані
Приклад "вкладеного" стану:
const [user, setUser] = useState({
name: "Alex",
address: { city: "Paris", zip: "75000" },
});Щоб оновити місто:
// доводиться копіювати всі рівні вручну
setUser(prev => ({
...prev,
address: { ...prev.address, city: "Lyon" },
}));Чим глибший об'єкт, тим більше шаблонного коду і вищий шанс помилки.
А якщо ти забудеш зробити копію (...prev.address),
React не помітить змін (зламається іммутабельність).
Проблема 2: важче мемоізувати й оптимізувати
Якщо в тебе є складний стан, наприклад:
const [state, setState] = useState({
user: { name: "Tim" },
theme: "dark"
});І ти оновлюєш лише theme:
setState(prev => ({ ...prev, theme: "light" }));то React все одно створює новий об'єкт state,
і всі його властивості отримують нові посилання.
Компоненти, що залежать лише від user,
теж перемалюються, хоча user не змінювався.
Втрата продуктивності й передбачуваності.
Проблема 3: складно робити часткові оновлення
React не "зливає" об'єкти автоматично (на відміну від класових компонентів з this.setState).
Тому тобі завжди доводиться вручну копіювати весь вкладений шлях.
Плаский стан вирішує це: ти оновлюєш лише потрібну частину, без зайвої вкладеності.
Переваги плаского стану
| Перевага | Чому це важливо |
|---|---|
| Простіше оновлювати | Не потрібно копіювати кілька рівнів |
| Менше багів | Менший ризик порушити іммутабельність |
| Швидший рендер | Локальні оновлення не торкаються всього дерева |
| Простіше тестувати | Можна ізолювати логіку зміни кожної частини |
| Легше думати | Стан стає декларативним і прозорим |
Приклад: "глибокий" vs "плаский"
Глибокий стан:
const [state, setState] = useState({
user: { name: "Tim", age: 25 },
settings: { theme: "dark", notifications: true },
});Оновлення теми:
setState(prev => ({
...prev,
settings: { ...prev.settings, theme: "light" },
}));Плаский стан:
const [user, setUser] = useState({ name: "Tim", age: 25 });
const [theme, setTheme] = useState("dark");
const [notifications, setNotifications] = useState(true);Оновлення теми:
setTheme("light");Просто, зрозуміло, безпечно.
Коли все ж можна використовувати вкладені структури
Іноді вкладеність доречна:
- при роботі з логічно цілісними даними (наприклад,
userабоaddress); - при використанні useReducer (він дозволяє оновлювати складні структури через редʼюсер);
- коли стан потрібно передавати "пакетом".
Але навіть тоді намагайся тримати структуру неглибокою (1-2 рівні максимум).
Підсумок
| Питання | Відповідь |
|---|---|
| Що означає "плаский стан"? | Мінімум вкладеності, кожне значення зберігається окремо |
| Чому React цього вимагає? | Так простіше оновлювати, порівнювати й оптимізувати |
| Що не так із вкладеними об'єктами? | Важко оновлювати й копіювати, вищий ризик багів |
| Коли можлива вкладеність? | В обмежених випадках, якщо дані логічно пов'язані |
| Ідеальний принцип | "Стан має бути настільки простим, наскільки це можливо, але не простіше." |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.