React useReducer Hook
The useReducer
hook is an alternative to useState for managing more complex state logic in React functional components. It is especially useful when the state depends on multiple actions or when state transitions are complex. The useReducer
hook uses a reducer function to manage state updates, similar to how reducers work in Redux.
1. Basic Counter Example using useReducer Hook
In this example, we create a simple counter component using useReducer
. The reducer function will handle two actions: increment and decrement. This example demonstrates the basic setup of the hook.
import React, { useReducer } from 'react';
function 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, { count: 0 }); // Initial state
return (
<div>
<h2>Count: {state.count}</h2>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
export default Counter;
Explanation:
reducer
: A function that takes the current state and an action, then returns the updated state.useReducer
: Initializes the state and provides adispatch
function to trigger actions.- When user clicks on Increment button,
dispatch({ type: 'increment' })
is called, and this sends an action to the reducer to update the state. - When user clicks on Decrement button,
dispatch({ type: 'decrement' })
is called, and this sends an action to the reducer to update the state.
Output:
2. Example: Form State Management using useReducer Hook
In this example, we use useReducer
to manage the state of a form with multiple fields. The reducer function handles updates to each field, making the code more organized compared to using multiple useState
hooks.
import React, { useReducer } from 'react';
function reducer(state, action) {
return {
...state,
[action.field]: action.value,
};
}
function Form() {
const [state, dispatch] = useReducer(reducer, { name: '', email: '' });
const handleChange = (e) => {
dispatch({ field: e.target.name, value: e.target.value });
};
return (
<div>
<label>
Name:
<input type="text" name="name" value={state.name} onChange={handleChange} />
</label>
<br />
<label>
Email:
<input type="email" name="email" value={state.email} onChange={handleChange} />
</label>
<br />
<p>Name: {state.name}</p>
<p>Email: {state.email}</p>
</div>
);
}
export default Form;
Explanation:
When user clicks on any of the inputs, handleChange
function is called, which calls dispatch
, which in turn sends an action to the reducer
function.
reducer
: Updates the specific field in the state based on the action.dispatch
: Handles updates to each input field dynamically.- This approach scales better than managing each input with separate
useState
hooks.
Output:
3. Example: Todo List with Add and Remove using useReducer Hook
In this example, we build a simple todo list where items can be added and removed. The reducer function handles the add
and remove
actions, and useReducer
manages the list state.
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'add':
return [...state, { id: Date.now(), text: action.text }];
case 'remove':
return state.filter(todo => todo.id !== action.id);
default:
return state;
}
}
function TodoList() {
const [state, dispatch] = useReducer(reducer, []);
const [text, setText] = React.useState('');
const handleAdd = () => {
dispatch({ type: 'add', text });
setText('');
};
return (
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Enter a todo"
/>
<button onClick={handleAdd}>Add</button>
<ul>
{state.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => dispatch({ type: 'remove', id: todo.id })}>Remove</button>
</li>
))}
</ul>
</div>
);
}
export default TodoList;
Explanation:
reducer
: Handlesadd
andremove
actions to update the todo list state.dispatch
: Adds new todos or removes existing ones based on the action type.- The list dynamically updates as items are added or removed, demonstrating the power of
useReducer
for list management.
Output:
Conclusion
The useReducer
hook is a versatile tool for managing complex state logic in React components. It is particularly helpful when you need to handle multiple related state transitions or actions. By using a reducer function, you can keep your state management logic clean and organized. Start practicing with useReducer
to simplify state management in your React projects!