Flux Pattern
Flux — архитектурный паттерн управления состоянием, предложенный Facebook, основанный на однонаправленном потоке данных: Action → Dispatcher → Store → View.
Зачем нужно
До Flux в крупных приложениях State Management был хаотичным: данные текли в обоих направлениях, компоненты напрямую вызывали методы друг друга, отследить источник изменений было сложно. Flux ввёл строгое правило: данные текут только в одном направлении. Это сделало изменения предсказуемыми и легко отлаживаемыми. Redux — самая известная реализация Flux-идей.
Где используется
- Redux — самая популярная реализация, де-факто стандарт для сложного state management в React
- Vuex (Vue 2) / Pinia (Vue 3) — Flux-вдохновлённые решения для Vue
- NgRx — Flux/Redux для Angular
- Zustand — упрощённая реализация без строгого Flux, но с похожей идеей
Однонаправленный поток данных
┌──────────┐ ┌────────────┐ ┌───────┐ ┌──────┐
│ Action │───►│ Dispatcher │───►│ Store │───►│ View │
│(действие)│ │(диспетчер) │ │ │ │ │
└──────────┘ └────────────┘ └───────┘ └──────┘
│
Пользователь нажал │
кнопку → создаётся │
новый Action ────────┘
Элементы паттерна
// ACTION — описывает что произошло (объект)
const addToCartAction = {
type: 'CART/ADD_ITEM',
payload: {
productId: '42',
name: 'Кофе',
price: 350,
quantity: 1,
},
};
// STORE — хранит состояние, реагирует на actions
// (В оригинальном Flux через Dispatcher, в Redux через reducer)
function cartReducer(state = { items: }, action) {
switch (action.type) {
case 'CART/ADD_ITEM':
const existing = state.items.find(i => i.productId === action.payload.productId);
if (existing) {
return {
...state,
items: state.items.map(item =>
item.productId === action.payload.productId
? { ...item, quantity: item.quantity + action.payload.quantity }
: item
),
};
}
return { ...state, items: [...state.items, action.payload] };
case 'CART/REMOVE_ITEM':
return {
...state,
items: state.items.filter(i => i.productId !== action.payload),
};
default:
return state;
}
}
// DISPATCHER — уведомляет все store об action
// В Redux это store.dispatch(action)
// VIEW — React-компонент читает state из Store и диспатчит actions
Flux без Redux (ванильная реализация)
// Простейший Store с EventEmitter
class CartStore extends EventEmitter {
#state = { items: };
dispatch(action) {
this.#state = cartReducer(this.#state, action);
this.emit('change'); // уведомляем подписчиков
}
getState {
return this.#state;
}
}
const store = new CartStore();
// View подписывается на изменения
store.on('change', () => {
renderCart(store.getState);
});
// Диспатч action при клике
document.getElementById('add-btn').addEventListener('click', () => {
store.dispatch({
type: 'CART/ADD_ITEM',
payload: { productId: '1', name: 'Кофе', price: 350, quantity: 1 },
});
});
Частые ошибки
- Flux для простого состояния — если компонент имеет 3 поля формы, Flux/Redux избыточен; используйте
useState. - Слишком мелкие actions —
SET_LOADING_TRUE,SET_LOADING_FALSEвместоFETCH_USERS_REQUEST/FETCH_USERS_SUCCESS/FETCH_USERS_FAILURE. - Мутация state в reducer — reducer должен возвращать новый объект, а не мутировать
state.items.push(...).
Связанные темы
- _MOC SPA
- Redux -- концепции и архитектура
- Локальное vs глобальное состояние
- State -- внутреннее состояние
- MVVM -- Model View ViewModel