How to use useReducer in React
useReducer
is a React Hook that provides an alternative to useState
for managing complex state logic in your components. It’s particularly useful when:
- You have state that involves multiple sub-values
- The next state depends on the previous one
- The state logic is complex enough to warrant moving it outside the component
Basic Syntax
const [state, dispatch] = useReducer(reducer, initialState);
state
: The current statedispatch
: A function to dispatch actions to the reducerreducer
: A function that takes the current state and an action and returns the new stateinitialState
: The initial state of the reducer
Example: Counter
const initialState = { count: 0 };
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
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>
</div>
);
}
Example 2: SignUp Form
import { useReducer } from 'react';
// Initial form state
const initialState = {
name: '',
email: '',
subscribed: false,
};
const formReducer = (state, action) => {
switch (action.type) {
case 'UPDATE_FIELD':
return {
...state,
[action.field]: action.value,
};
case 'TOGGLE_SUBSCRIPTION':
return {
...state,
subscribed: !state.subscribed,
};
case 'RESET':
return initialState;
default:
return state;
}
}
export default function SignupForm() {
const [state, dispatch] = useReducer(formReducer, initialState);
const handleChange = (e) => {
dispatch({
type: 'UPDATE_FIELD',
field: e.target.name,
value: e.target.value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form submitted:', state);
dispatch({ type: 'RESET' });
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input name="name" value={state.name} onChange={handleChange} />
</label>
<label>
Email:
<input name="email" value={state.email} onChange={handleChange} />
</label>
<label>
<input
type="checkbox"
checked={state.subscribed}
onChange={() => dispatch({ type: 'TOGGLE_SUBSCRIPTION' })}
/>
Subscribe to newsletter
</label>
<button type="submit">Submit</button>
</form>
);
}
Summary
- Use
useReducer
when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one - Use cases: Managing complex state, state logic outside the component