Fundamentals

Філософія Redux та Три Принципи

Redux часто вважають складною бібліотекою, але насправді він базується на кількох дуже простих ідеях. Складність виникає не з самої бібліотеки, а з нових термінів та обмежень, які вона накладає.

Філософія Redux та Три Принципи

Redux часто вважають складною бібліотекою, але насправді він базується на кількох дуже простих ідеях. Складність виникає не з самої бібліотеки, а з нових термінів та обмежень, які вона накладає.

Але ці обмеження існують не просто так. Вони — це те, що робить ваш код передбачуваним.

Що таке Redux?

Формально: Redux — це контейнер передбачуваного стану для JavaScript-додатків.

Це означає, що:

  1. Він зберігає дані (контейнер).
  2. Дані змінюються передбачувано (ми точно знаємо, хто, коли і як їх змінив).
  3. Він не прив'язаний до React (можна використовувати з Angular, Vue, або навіть vanilla JS).

Історично Redux був створений Dan Abramov та Andrew Clark у 2015 році як реалізація архітектури Flux (від Facebook), але спрощена і покращена ідеями з мови Elm.

Три Принципи Redux

Уся "магія" Redux тримається на трьох китах. Якщо ви зрозумієте їх, ви зрозумієте Redux.

1. Єдине джерело правди (Single Source of Truth)

Весь стан вашого додатку зберігається в дереві об'єктів всередині одного Store.

На відміну від Flux, де могло бути багато Store-ів, у Redux Store завжди один. Це як гігантський JSON-об'єкт, що описує весь ваш додаток.

// Приклад того, як виглядає Store всередині
const state = {
    user: {
        id: 1,
        name: 'Ivan',
        role: 'admin',
    },
    todos: [
        { id: 1, text: 'Вивчити Redux', completed: false },
        { id: 2, text: 'Написати код', completed: true },
    ],
    visibilityFilter: 'SHOW_ALL',
}

Переваги:

  • Легко зберігати стан на сервері та відновлювати його (SSR).
  • Легко дебажити (весь стан в одному місці).
  • Легко реалізувати функції на кшталт Undo/Redo.

2. Стан доступний лише для читання (State is Read-Only)

Єдиний спосіб змінити стан — це відправити (dispatch) Action (дію), об'єкт, що описує, що сталося.

Ви не можете написати state.user.name = 'Petro'. Це заборонено. Замість цього ви кажете системі: "Гей, користувач хоче змінити ім'я".

Це робиться через простий об'єкт:

// Action
{
  type: 'UPDATE_USER_NAME',
  payload: 'Petro'
}

Це гарантує, що ні потік з мережі, ні подія миші не можуть записати щось у стан безпосередньо. Усі зміни централізовані та відбуваються в строгому порядку.

3. Зміни вносяться чистими функціями (Changes are made with Pure Functions)

Щоб описати, як саме стан змінюється у відповідь на actions, ви пишете Reducers (редюсери).

Reducer — це просто функція, яка бере попередній стан і дію, а повертає новий стан.

// (PreviousState, Action) => NewState
function userReducer(state, action) {
    if (action.type === 'UPDATE_USER_NAME') {
        return {
            ...state,
            name: action.payload,
        }
    }
    return state
}

Важливо: Редюсер не змінює існуючий об'єкт state. Він створює новий об'єкт з оновленими даними. Це і є принцип Іммутабельності, про який ми поговоримо детальніше в наступному уроці.

Однонаправлений потік даних (Data Flow)

У Redux дані завжди рухаються в одному напрямку (Unidirectional Data Flow). Це відрізняє його від двостороннього зв'язування (Two-way data binding), яке було популярне в ранніх фреймворках (наприклад, AngularJS).

Життєвий цикл даних у Redux виглядає так:

Loading diagram...
sequenceDiagram
participant UI as User Interface
participant Action as Action
participant Reducer as Reducer
participant Store as Redux Store

    UI->>Store: 1. Dispatch(Action)
    Note over UI, Store: Користувач натиснув кнопку

    Store->>Reducer: 2. Call Reducer(CurrentState, Action)

    Reducer->>Reducer: 3. Logic Execution
    Note right of Reducer: Обчислення нового стану

    Reducer->>Store: 4. Return NewState

    Store->>UI: 5. Subscribe Notification
    Note over Store, UI: Оновлення UI

Детальний розбір циклу:

  1. Подія: Щось трапляється в додатку (клік кнопки, прийшли дані з API).
  2. Dispatch: UI компонент відправляє Action в Store.
    • dispatch({ type: 'DEPOSIT', payload: 10 })
  3. Reducer: Store викликає функцію-редюсер, передаючи їй поточний стан і цей action.
    • reducer({ balance: 0 }, { type: 'DEPOSIT', payload: 10 })
  4. Update: Редюсер повертає новий стан.
    • return { balance: 10 }
  5. Re-render: Store зберігає новий стан і повідомляє всі підписані UI компоненти, що дані змінилися. Компоненти перемальовуються з новими даними.

Цей цикл робить поведінку програми надзвичайно передбачуваною. Якщо ви бачите неправильні дані на екрані, ви точно знаєте, що це сталося через якийсь конкретний Action, який був неправильно оброблений Reducer-ом.


Але чому так важливо "не змінювати" стан, а "створювати новий"? Чому не можна просто зробити state.value++? Про це — у наступному розділі про чистоту функцій.

👉 Далі: Чисті функції та Іммутабельність

Copyright © 2026