Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить «state normalization»?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**State normalization** - це спосіб зберігати дані у стані в «плоскій», структурованій формі, щоб уникнути дублювання даних, спростити оновлення та зменшити кількість ререндерів. **Ключове:** один об'єкт зберігається в одному місці, а інші сутності посилаються на нього через ID, тому при зміні не потрібно оновлювати всі копії.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке нормалізація стану **State normalization** - це спосіб **зберігати дані у стані в «плоскій», структурованій формі**, щоб: - **уникнути дублювання** даних, - **спростити оновлення**, - **зменшити кількість ререндерів**, - і зробити дані **передбачуваними** та **легко кешованими**. --- ### Приклад без нормалізації (погано) ```javascript const state = { posts: [ { id: 1, title: "React guide", author: { id: 10, name: "Tim" } }, { id: 2, title: "Redux patterns", author: { id: 10, name: "Tim" } // the author is duplicated } ] }; ``` Тут об'єкт автора дублюється в кожному пості. Якщо автор змінить ім'я, потрібно пройтися по всіх постах і оновити копію. Крім того, кожна зміна в posts спричиняє масові ререндери. --- ### Приклад із нормалізацією ```javascript const state = { posts: [1, 2], // just IDs users: { // dictionary of entities by ID 10: { id: 10, name: "Tim" } }, entities: { posts: { 1: { id: 1, title: "React guide", authorId: 10 }, 2: { id: 2, title: "Redux patterns", authorId: 10 } } } }; ``` Тепер: - Автор зберігається в одному місці (users[10]); - Пости посилаються на автора через authorId; - При зміні автора не потрібно оновлювати всі пости. --- ## Чому це важливо для продуктивності React 1. **Менше ререндерів** - Під час оновлення сутності React може перемалювати лише ті компоненти, які залежать від конкретного ID. - Немає «ланцюгової» реакції через вкладені об'єкти. 2. **Легко порівнювати дані (shallow compare)** - Об'єкти й масиви менш вкладені -> === і React.memo працюють ефективніше. 3. **Спрощуються оновлення** - Зміна конкретного елемента - просто оновлення state.entities.posts[id]. - Не потрібно перебирати весь масив. 4. **Оптимізується кеш і селектори** - Мемоізовані селектори (наприклад, у Redux Toolkit з createSelector) працюють швидше і стабільніше. --- ## Аналогія Уяви, що твій state - це база даних у мініатюрі. Нормалізація перетворює його на таблиці зі зв'язками (1:1, 1:n), замість вкладених об'єктів (як «JSON у JSON»). --- ## У React / Redux це особливо корисно У Redux Toolkit і RTK Query це рекомендована практика. Офіційна бібліотека normalizr навіть автоматизує перетворення: ```javascript import { normalize, schema } from 'normalizr'; const user = new schema.Entity('users'); const post = new schema.Entity('posts', { author: user }); const normalizedData = normalize(originalData, [post]); ``` Результат: ```javascript { entities: { users: { '10': { id: 10, name: 'Tim' } }, posts: { '1': { id: 1, title: 'React guide', author: 10 }, '2': { id: 2, title: 'Redux patterns', author: 10 } } }, result: ['1', '2'] } ``` --- ## Приклад у контексті React-компонентів ### Без нормалізації: ```javascript function Post({ post }) { return ( <div> <h2>{post.title}</h2> <p>{post.author.name}</p> </div> ); } ``` Якщо оновиться ім'я автора, React перерендерить усі пости, тому що post.author - новий об'єкт у кожному. --- ### З нормалізацією: ```javascript function Post({ postId }) { const post = useSelector(state => state.entities.posts[postId]); const author = useSelector(state => state.entities.users[post.authorId]); return ( <div> <h2>{post.title}</h2> <p>{author.name}</p> </div> ); } ``` Тепер оновлення author.name торкнеться лише тих компонентів, які залежать від authorId, а не всього списку постів. --- ## Додаткові переваги нормалізації | Перевага | Опис | |---|---| | Проста структура | Завжди знаєш, де шукати дані | | Легко оновлювати і видаляти | Змінюєш за ID, без складних вкладеностей | | Чіткі зв'язки між сутностями | «Один до багатьох», «багато до багатьох» | | Сумісно з селекторами | Чудово працює з мемоізацією (useMemo, reselect) | | Менше JSON parsing і diffing | Достатньо поверхневого порівняння | --- ## Коли не варто нормалізувати Надмірна нормалізація шкідлива, якщо: - Даних небагато (10-20 записів, проста форма); - Оновлення рідкісні й не зачіпають піддерева; - Структура даних статична (наприклад, список вкладок або просте меню). Нормалізація потрібна там, де є взаємопов'язані дані та багато оновлень. --- ## Підсумок | Що робить | Навіщо потрібно | |---|---| | Зберігає дані «плоско» (за ID) | Позбавляє від дублювання | | Зберігає зв'язки через ID | Дозволяє оновлювати лише потрібні сутності | | Зменшує кількість ререндерів | Підвищує продуктивність | | Робить логіку простішою | Дані стають передбачуваними | | Працює як міні-база даних | Легко оновлювати, шукати і кешувати | --- State normalization = база даних усередині React-стану. > Одне джерело істини для кожної сутності: менше ререндерів, менше багів, вища продуктивність.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.