?? Mastering React Hooks: A Beginner's Guide to useReducer
SRINIVAS K
Serving NP | Software Engineer specializing in React, TypeScript, JavaScript and Next.js | Building Scalable Web Applications with a Focus on Performance
?? Promo:
Since we discussed how to store data with and without triggering re-renders using useState and useRef, now we’ll see how we can manage multiple pieces of state together efficiently using useReducer.
When managing complex state logic in React, the useReducer hook is a powerful alternative to useState. It’s especially useful for managing multiple pieces of state or when state updates depend on previous values. Let’s dive into how useReducer works and why it can be the right tool for your React projects.
?? What is useReducer?
useReducer is a hook that helps manage complex state logic by breaking state updates into actions and a reducer function. It’s ideal for cases where useState can become overwhelming, like when you have many state transitions or need to centralize state management.
The basic syntax:
const [state, dispatch] = useReducer(reducer, initialState);
Here’s a simple example:
import React, { useReducer } from 'react';
// Define the reducer function
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};
// Initialize the initial state
const initialState = { count: 0 };
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
?? Breakdown:
? Important Concepts to Master:
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }; // Correct: centralized logic in the reducer
default:
return state;
}
};
const [count, setCount] = useState(0);
// ? Wrong: state logic is scattered and hard to maintain
setCount(count + 1);
setCount(count - 1);
// ? Correct: state logic is handled in one place in `useReducer`
dispatch({ type: 'increment' });
dispatch({ type: 'decrement' });
When to Use useReducer useReducer is best for situations where:
领英推荐
Initial State with Lazy Initialization
Like useState, useReducer supports lazy initialization, where the initial state is computed with a function:
const [state, dispatch] = useReducer(reducer, 0, init => ({ count: init }));
Using Multiple Reducers
In more complex applications, you can use multiple useReducer calls to manage different parts of the state independently:
const [state1, dispatch1] = useReducer(reducer1, initialState1);
const [state2, dispatch2] = useReducer(reducer2, initialState2);
???? Practical Example: Managing a Todo List
Let’s take an example where we use useReducer to manage a todo list:
function todosReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, { id: Date.now(), text: action.payload }];
case 'remove':
return state.filter(todo => todo.id !== action.payload);
default:
return state;
}
}
function TodoApp() {
const [todos, dispatch] = useReducer(todosReducer, []);
const [text, setText] = useState('');
const handleAddTodo = () => {
dispatch({ type: 'add', payload: text });
setText(''); // Reset input after adding a todo
};
return (
<div>
<input value={text} onChange={e => setText(e.target.value)} />
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => dispatch({ type: 'remove', payload: todo.id })}>Remove</button>
</li>
))}
</ul>
</div>
);
}
In this example, we manage the list of todos with useReducer. The add and remove actions allow us to modify the todo list based on user input, centralizing the state management logic.
?? Conclusion:
useReducer is a powerful hook for managing complex state logic in React. It is especially useful for handling multiple related pieces of state and centralizing state transitions. For larger applications where state management grows, useReducer can provide cleaner and more maintainable code.
?? Tip: Use useReducer when you have multiple, interdependent state updates or more complex state logic. Happy coding!
?? What Next:
Now that we know how to manage multiple states inside a component, what if we need to have some common store that can be accessed by sibling components? Can you guess the hook that will help with this? Stay tuned to find out!
Serving NP | Software Engineer specializing in React, TypeScript, JavaScript and Next.js | Building Scalable Web Applications with a Focus on Performance
5 天前checkout the new article to share state without props drilling: --> https://www.dhirubhai.net/posts/srinivasthedeveloper_reactjs-reacthooks-usecontext-activity-7255968936045785088-glQl