Flux и Redux pattern
Однонаправленный поток данных для предсказуемого управления состоянием приложения.
Зачем нужно
- Предсказуемость: состояние меняется только через actions
- Отладка: time-travel debugging, логирование каждого изменения
- Масштабируемость: единый store для всего приложения
Где используется
- React-приложения (Redux, Redux Toolkit, Zustand), Vue (Vuex/Pinia)
Flux (концепция Facebook)
Action → Dispatcher → Store → View → Action
- Action -- объект с типом события и данными
- Dispatcher -- центральный хаб, рассылает actions в stores
- Store -- хранит состояние и логику
- View -- React-компонент, подписан на store
Redux (упрощённый Flux)
Action → Reducer → Store → Component
Три принципа
- Единый store -- одно дерево состояния
- Read-only state -- изменения только через dispatch(action)
- Pure reducers -- чистые функции
(state, action) => newState
Пример (Redux Toolkit)
import { createSlice, configureStore } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
decrement: (state) => { state.value -= 1; },
addBy: (state, action) => { state.value += action.payload; },
},
});
export const { increment, decrement, addBy } = counterSlice.actions;
const store = configureStore({
reducer: { counter: counterSlice.reducer },
});
// Использование
store.dispatch(increment);
console.log(store.getState.counter.value); // 1
В React-компоненте
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';
function Counter() {
const count = useSelector((s: RootState) => s.counter.value);
const dispatch = useDispatch;
return <button onClick={ => dispatch(increment)}>{count}</button>;
}
Когда НЕ нужен Redux
- Маленькое приложение (хватит useState/useContext)
- Серверное состояние (лучше React Query / SWR)