← Назад к вопросам
Как action попадет в store?
2.0 Middle🔥 201 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как action попадет в store?
Общая архитектура (Flux паттерн)
Action — это объект, содержащий информацию о том, что произошло. Store — это хранилище состояния. Путь от action к store зависит от выбранной библиотеки.
Redux: Классический подход
В Redux есть четкий flow (Flux):
UI (dispatch) -> Action -> Reducer -> Store -> View Update
Пример:
// 1. Определяем action
const INCREMENT = 'INCREMENT';
const increment = (amount) => ({
type: INCREMENT,
payload: amount
});
// 2. Определяем reducer (чистая функция)
function counterReducer(state = 0, action) {
switch (action.type) {
case INCREMENT:
return state + action.payload;
default:
return state;
}
}
// 3. Создаем store
const store = createStore(counterReducer);
// 4. Dispatch action из компонента
function Counter() {
const dispatch = useDispatch();
const count = useSelector(state => state);
return (
<div>
<p>{count}</p>
{/* Action отправляется -> редьюсер -> новое состояние -> re-render */}
<button onClick={() => dispatch(increment(1))}>+1</button>
</div>
);
}
Как это работает:
dispatch(increment(1))отправляет action{ type: 'INCREMENT', payload: 1 }- Store пропускает action через reducer
- Reducer возвращает новое состояние
- Store обновляется и уведомляет подписчиков
- Компонент перерендерится с новым значением
Effector: Граф вычислений
В Effector нет редьюсеров, вместо этого используется событийная модель:
// 1. Создаем event (как action)
const incremented = createEvent('incremented');
// 2. Создаем store с изначальным значением
const $counter = createStore(0);
// 3. Связываем event с обновлением store
$counter.on(incremented, (state, amount) => state + amount);
// 4. В компоненте вызываем event
function Counter() {
const counter = useUnit($counter);
const handleClick = useUnit(incremented);
return (
<div>
<p>{counter}</p>
{/* Клик -> event -> обновление store -> re-render */}
<button onClick={() => handleClick(1)}>+1</button>
</div>
);
}
Flow в Effector:
handleClick(1) -> incremented(1) -> $counter.on(...) -> обновление $counter -> подписчики
Zustand: Простой и минималистичный
import create from 'zustand';
// 1. Создаем store с actions
const useCounterStore = create((set) => ({
count: 0,
// Action — это метод в store
increment: (amount) => set((state) => ({
count: state.count + amount
})),
decrement: (amount) => set((state) => ({
count: state.count - amount
}))
}));
// 2. В компоненте вызываем action
function Counter() {
const { count, increment } = useCounterStore();
return (
<div>
<p>{count}</p>
{/* increment -> set -> обновление store -> re-render */}
<button onClick={() => increment(1)}>+1</button>
</div>
);
}
MobX: Reactive Programming
class CounterStore {
count = 0;
// Action
increment(amount) {
this.count += amount; // Прямое изменение state
}
}
const counterStore = new CounterStore();
function Counter() {
// MobX автоматически отслеживает изменения
return (
<div>
<p>{counterStore.count}</p>
{/* Action -> изменение свойства -> re-render через mobx-react */}
<button onClick={() => counterStore.increment(1)}>+1</button>
</div>
);
}
Реальный пример с асинхронностью (Redux Thunk)
// Action creator, который возвращает функцию
const fetchUser = (userId) => async (dispatch) => {
dispatch({ type: 'LOADING' });
try {
const user = await api.getUser(userId);
// Второе action после успешной загрузки
dispatch({ type: 'LOADED', payload: user });
} catch (error) {
dispatch({ type: 'ERROR', payload: error });
}
};
// В компоненте
function UserProfile({ userId }) {
const dispatch = useDispatch();
const { user, loading, error } = useSelector(state => state.user);
useEffect(() => {
// dispatch отправляет thunk вместо простого action
dispatch(fetchUser(userId));
}, [userId, dispatch]);
if (loading) return <Spinner />;
if (error) return <Error msg={error} />;
return <div>{user.name}</div>;
}
Диаграмма всех подходов
Redux: dispatch(action) -> middleware -> reducer -> store
Effector: event(data) -> .on() handlers -> store -> subscriptions
Zustand: action() -> set() -> store -> subscriptions
MobX: mutate state -> reactivity -> re-render
Context: setState() -> Provider value -> useContext() -> re-render
Ключевые принципы
- Action — это описание того, что произошло
- Reducer/Handler — определяет, как обновить state
- Store — хранит текущее состояние
- Subscription — компоненты подписаны на изменения
- Re-render — когда state изменяется, компонент перерендерится
Заключение
Основной pattern остается один и тот же во всех библиотеках:
Action -> (Reducer/Handler/Mutation) -> Store -> Component Update
Выбор инструмента зависит от сложности приложения и предпочтений команды. Redux подходит для больших приложений, Zustand для простых, Effector для сложной логики, MobX для реактивного стиля.