useReducer
— это хук (hook) в React, который является альтернативой useState
для управления сложным состоянием компонента. Он особенно полезен, когда состояние содержит множественные подзначения или когда следующее состояние зависит от предыдущего.
Редюсер (Reducer) — чистая функция, которая принимает предыдущее состояние и действие (action), возвращая новое состояние
(state, action) => newState
Действие (Action) — объект, описывающий что произошло, обычно содержит type
и дополнительные данные
Инициализатор (Initializer) — функция для ленивой инициализации начального состояния
const [state, dispatch] = useReducer(reducer, initialArg, init);
Где:
reducer
— функция-редюсерinitialArg
— начальное состояние или аргумент для инициализатораinit
(опционально) — функция инициализацииconst initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return initialState;
default:
throw new Error('Unknown action type');
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
function init(initialCount) {
return { count: initialCount };
}
function Counter({ initialCount }) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
// ...
}
// Действие с payload (полезной нагрузкой)
dispatch({
type: 'ADD_TODO',
payload: { id: 1, text: 'Learn useReducer' }
});
// Редюсер с обработкой payload
function todosReducer(state, action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
// ...
}
}
const StateContext = createContext();
const DispatchContext = createContext();
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
<ChildComponent />
</DispatchContext.Provider>
</StateContext.Provider>
);
}
function ChildComponent() {
const state = useContext(StateContext);
const dispatch = useContext(DispatchContext);
// ...
}
const formReducer = (state, action) => {
switch (action.type) {
case 'FIELD_CHANGE':
return {
...state,
[action.field]: action.value,
isDirty: true
};
case 'SUBMIT':
return { ...state, isSubmitting: true };
case 'SUBMIT_SUCCESS':
return { ...initialState, isSuccess: true };
default:
return state;
}
};
function Form() {
const [state, dispatch] = useReducer(formReducer, {
username: '',
email: '',
isDirty: false,
isSubmitting: false,
isSuccess: false
});
const handleSubmit = (e) => {
e.preventDefault();
dispatch({ type: 'SUBMIT' });
// API call...
dispatch({ type: 'SUBMIT_SUCCESS' });
};
return (
<form onSubmit={handleSubmit}>
<input
value={state.username}
onChange={(e) => dispatch({
type: 'FIELD_CHANGE',
field: 'username',
value: e.target.value
})}
/>
{/* другие поля */}
</form>
);
}
useReducer
— это мощная альтернатива useState
для управления сложным состоянием в React-компонентах. Он обеспечивает предсказуемые обновления состояния через систему действий (actions) и редюсеров (reducers), что особенно полезно для сложной бизнес-логики. Хук идеально подходит для форм, сложных виджетов и глобального состояния приложения, особенно в комбинации с контекстом. Понимание useReducer
важно для разработки масштабируемых React-приложений и является фундаментальным навыком профессионального React-разработчика.