Redux — предвидим контейнер за управление на състоянието за JavaScript приложения, създаден от Дан Абрамов през 2015 г. Redux реализира еднопосочен поток от данни, базиран на архитектурата Flux: състоянието се съхранява в единен Store, променя се само чрез чисти функции Reducer и се инициира чрез Action с Dispatch. Според данните на npm Trends, Redux запазва над 7 милиона седмични изтегляния, оставайки стандарт за управление на състоянието в React Native и уеб приложения.
Основни моменти
Redux — архитектурен модел и библиотека за управление на състоянието, основан на три принципа: единствен източник на истина (single source of truth), състояние само за четене (read-only) и промени чрез чисти функции. За разлика от MVC, където моделът може да променя състоянието непредвидимо, Redux гарантира детерминизъм: при едни и същи входни данни резултатът винаги е един и същ.
Redux е вдъхновен от архитектурата Flux на Facebook и езика Elm. Основната разлика от Flux — единен Store вместо няколко. В Redux цялото състояние на приложението — обекти, масиви, флагове за зареждане — се съхранява в едно дърво. Това опростява отстраняването на грешки, тестването и възстановяването на състоянието (time-travel debugging). Разработчикът може да запази целия Store, да възпроизведе последователността от Action и да види как състоянието се е променяло на всяка стъпка.
Според данните на State of JS 2025, 68% от респондентите, използващи управление на състоянието, избират Redux или Redux Toolkit. Инструментът се поддържа от всички съвременни рамки: React, React Native, Angular, Vue и дори чист JavaScript без рамки.
Unidirectional data flow — ключовият принцип на Redux, при който данните се движат строго в една посока: View → Action → Dispatch → Reducer → Store → View. Никой компонент не може директно да промени Store. View само се абонира за промени чрез useSelector или connect и инициира промени чрез dispatch.
Цикъл на работа на Redux: потребителят натиска бутон → компонентът извиква dispatch({ type: 'INCREMENT' }) → Store предава Action на Root Reducer → Reducer изчислява ново състояние → Store уведомява абонатите → View се прерисува с нови данни. Този цикъл гарантира, че всяка промяна има ясна причина под формата на конкретен Action.
DevTools — вграденият инструмент на Redux за наблюдение на всеки Action, състоянието на Store и времето за изпълнение. Разработчикът вижда списък на всички изпратени Action, разликата в състоянието (diff) преди и след, и може да се върне към всяко предишно състояние. Това прави отстраняването на грешки на сложни състояния десетки пъти по-бързо в сравнение с обикновеното логване.
Store — обект, съдържащ цялото дърво на състоянието. Създава се чрез configureStore (RTK) или createStore. Store предоставя три метода: getState() за четене, dispatch(action) за промяна и subscribe(listener) за абонамент. В Redux Toolkit Store вече включва middleware, DevTools и поддръжка за slice.
import { configureStore } from '@reduxjs/toolkit'
interface CounterState {
value: number
}
const initialState: CounterState = { value: 0 }
function counterReducer(
state = initialState,
action: { type: string }
): CounterState {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 }
default:
return state
}
}
const store = configureStore({ reducer: counterReducer })
store.dispatch({ type: 'INCREMENT' })
console.log(store.getState()) // { value: 1 }Action и Action Creator — Action е обект със задължително поле type (константа-низ) и опционално payload (данни). Action Creator — функция, която връща Action. В Redux Toolkit се използва createAction за генериране на Action с автоматично типизиране.
Reducer — чиста функция, получаваща текущото състояние и Action, връщаща ново състояние. Reducer не трябва: да мутира state (връща нов обект), да вика API, да генерира случайни числа или да има достъп до Date. Неизменяемостта се осигурява от spread оператора ... или Immer (вграден в RTK).
| Компонент | Отговорност | Ограничения |
|---|---|---|
| Store | Съхранение на състояние, dispatch, subscribe | Едно на приложение |
| Action | Описание на намерение за промяна на състоянието | Трябва да има type |
| Reducer | Изчисляване на ново състояние | Чиста функция, без странични ефекти |
| Dispatch | Изпращане на Action към Reducer | По подразбиране синхронен |
| Selector | Извличане на данни от Store | Мемоизация чрез createSelector |
Middleware — верига от функции, вмъкната между извикването на dispatch и момента, в който Action достига до Reducer. Всеки middleware получава API на Store и може да логва, модифицира, забавя или отменя Action. Redux Thunk — стандартен middleware за асинхронни операции, позволяващ dispatch-ване на функции вместо обекти.
import { createAsyncThunk } from '@reduxjs/toolkit'
export const fetchUser = createAsyncThunk(
'users/fetchById',
async (userId: number, { rejectWithValue }) => {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok)
return rejectWithValue('Failed to fetch')
return await response.json()
}
)Популярни middleware: Redux Thunk — за прости асинхронни извиквания, Redux Saga — за сложни сценарии със saga-генератори (debounce, race, паралелни заявки), Redux Observable — базиран на RxJS за реактивни потоци. В Redux Toolkit middleware се свързва чрез параметъра middleware в configureStore.
Според проучването на State of JS 2025, Thunk се използва в 72% от Redux проектите, Saga — в 18%, Observable — в 5%. За повечето приложения комбинацията Thunk + RTK Query е достатъчна, за да покрие 95% от сценариите за асинхронна работа с данни.
Redux Toolkit (RTK) — официалният, препоръчителен начин за писане на Redux логика, пуснат през 2019 г. RTK включва configureStore, createSlice, createAsyncThunk и createEntityAdapter, намалявайки boilerplate кода на Redux с 60-70%. Вместо ръчно създаване на Action Creator, Reducer и типове, се използва един createSlice.
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) { state.value += 1 },
incrementByAmount(state, action: PayloadAction<number>) {
state.value += action.payload
}
}
})
export const { increment, incrementByAmount } = counterSlice.actions
export default counterSlice.reducerRTK Query — вградено решение за работа с API, базирано на Redux Toolkit. Позволява декларативно дефиниране на endpoints чрез createApi с автоматично генериране на hooks, кеширане, инвалидиране на тагове и оптимистични актуализации. RTK Query замества ръчното писане на Thunk, Reducer и Selector за всяка API заявка.
Entity Adapter — помощният инструмент createEntityAdapter за нормализиране на колекции от обекти. Предоставя вградени CRUD reducer-и, selector-и и сортиране за масиви от обекти. Ако в Store се съхраняват списъци с потребители, продукти или поръчки — Entity Adapter намалява кода за редукция с 80%.
React Native Redux — стандартната комбинация за мобилни приложения в JavaScript. Redux се интегрира чрез Provider от react-redux, който обгръща коренния компонент на приложението. Хуковете useSelector и useDispatch дават на компонентите достъп до състоянието без props drilling. Persist — redux-persist запазва Store в AsyncStorage или MMKV, възстановявайки състоянието след рестартиране на приложението.
Middleware за React Native: redux-flipper за отстраняване на грешки чрез Flipper, redux-observable за реактивни потоци с native драйвери, react-native-mmkv за бързо постоянно хранилище. Навигационният плъгин redux-first-router свързва екраните със Store, позволявайки възстановяване на състоянието на екрана при връщане.
В React Native Redux се използва заедно със стратегията network-first: приложението първо се опитва да зареди данни от сървъра, след което ги кешира в Store чрез RTK Query или redux-persist. Офлайн режимът се постига чрез комбинация от Redux + NetInfo + опашка от Action за повторно изпращане при възстановяване на връзката.
Често задавани въпроси
Redux — пълноценно решение със Store, DevTools, Middleware и неизменимо състояние. Context API — вграден механизъм на React за предаване на данни без props drilling. Context е подходящ за глобални теми и локализация, Redux — за сложно състояние с асинхронни операции, кеширане и отстраняване на грешки. В големи приложения Context причинява ненужни прерисувания, Redux със selector-и решава този проблем.
Immer — библиотека за неизменима работа със състояние, вградена в Redux Toolkit. Immer позволява писане на reducer-и така, сякаш директно мутирате state: state.value += 1. Под капака Immer създава прокси обект (draft), проследява промените и връща нов неизменим обект. Това намалява обема на кода на reducer-ите с 50% и елиминира случайни мутации.
Redux логиката се тества изолирано: Reducer — чиста функция, достатъчно е да се извика с различни Action и да се провери резултатът. Action Creator — проверете върнатия обект. Thunk — мокнете API, извикайте dispatch и проверете кои Action са били изпратени. Компонент с useSelector — използвайте Provider с тестов Store в рендерера. Redux DevTools помагат да напишете тест, възпроизвеждайки последователността от Action от реална сесия.
useState е достатъчен за локално състояние на един компонент: текст на поле, отворен/затворен модал. Redux е необходим, когато състоянието се споделя между много екрани, изисква асинхронна синхронизация (данни от сървъра), трябва да се запази между рестартирания на приложението (persist) или изисква time-travel отстраняване на грешки. За малки приложения Redux е излишен — използвайте Context + useReducer.
Normalizr — библиотека за нормализиране на вложени данни в плоска структура на Store. Вместо съхранение на дълбоки обекти като user.posts[0].comments, нормализирането създава речници: entities.users, entities.posts, entities.comments с препратки по ID. Това опростява актуализирането на един обект на всички места и ускорява selector-ите. Redux Toolkit препоръчва нормализирани данни за сложни модели.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също