Both useReducer
and Redux are used for state management in React, but they serve different purposes and have different scopes. Let's break it down:
1. useReducer
(React Hook)
- Scope: Manages local component state.
- Usage: Used when state logic is complex and involves multiple actions.
- Data Flow: State is managed locally within a component.
- Setup: Lightweight and does not require external dependencies.
- Best For: Component-level state management.
Example of useReducer
import React, { useReducer } from "react";
// Initial state
const initialState = { count: 0 };
// Reducer function
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
};
export default Counter;
Key Takeaway: useReducer
is ideal for managing complex state logic within a single component or a small component tree.
2. Redux (Global State Management)
- Scope: Manages global application state.
- Usage: Used when multiple components across the application need to access and update the same state.
- Data Flow: Uses a centralized store to manage state globally.
-
Setup: Requires external dependencies (
redux
,react-redux
). - Best For: Large applications with complex state management needs.
Example of Redux
1. Install Dependencies
npm install @reduxjs/toolkit react-redux
2. Create Redux Slice (counterSlice.js
)
import { createSlice } from "@reduxjs/toolkit";
const counterSlice = createSlice({
name: "counter",
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
decrement: (state) => {
state.count -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
3. Configure Redux Store (store.js
)
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
4. Provide Redux Store to App (index.js
)
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
5. Use Redux in Components (Counter.js
)
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { increment, decrement } from "./counterSlice";
const Counter = () => {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
</div>
);
};
export default Counter;
Key Takeaway: Redux is more powerful and suited for managing application-wide state, making it ideal for large-scale applications.
๐ Differences
Feature |
useReducer (React Hook) |
Redux (Global State) |
---|---|---|
Scope | Local component state | Global application state |
Best For | Small-scale state management | Large-scale, complex apps |
Setup | No external dependencies | Requires redux & react-redux
|
Performance | Lightweight | Can be optimized with middleware like RTK Query
|
State Sharing | Limited to component tree | Shared across multiple components |
When to Use What?
โ Use useReducer
when:
- You need complex state logic inside a single component.
- The state is not required across multiple components.
โ Use Redux when:
- You need a global state that multiple components depend on.
- You want a predictable, centralized state management system.