1. Counter with multiple actions :
CODE :
import { useReducer } from 'react'
import './App.css'
function App() {
function reducerFn(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 }
case "decrement":
return { count: state.count - 1 }
case "reset":
return { count: state.count = 0 }
}
}
const [state, dispatch] = useReducer(reducerFn, { count: 0 })
return (
<div>
<h1>count:{state.count}</h1>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
)
}
export default App;
OUTPUT :
SCENARIO QUESTION :
Why is useReducer better than useState when multiple actions exist?
✓ useReducer centralizes all state update logic in one reducer function.
✓ Easy to manage multiple actions like INCREMENT, DECREMENT, RESET.
✓ Makes code more organized and scalable.
2. Login form state management :
A login form should manage username,password,error message and loading state.
CODE :
import React, { useReducer } from 'react'
function Login() {
const initialState = {
username: "",
password: "",
loading: false,
error: "",
isAuthenticated: false,
};
const LOGIN_START = "LOGIN_START";
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGIN_ERROR = "LOGIN_ERROR";
const LOGOUT = "LOGOUT";
const SET_USERNAME = "SET_USERNAME";
const SET_PASSWORD = "SET_PASSWORD";
const loginReducer = (state, action) => {
switch (action.type) {
case LOGIN_START:
return {
...state,
loading: true,
error: "",
};
case LOGIN_SUCCESS:
return {
...state,
loading: false,
isAuthenticated: true,
error: "",
};
case SET_USERNAME:
return {
...state,
username: action.payload,
};
case SET_PASSWORD:
return {
...state,
password: action.payload,
};
case LOGIN_ERROR:
return {
...state,
loading: false,
error: action.payload,
isAuthenticated: false,
};
case LOGOUT:
return {
...state,
username: "",
password: "",
loading: false,
error: "",
isAuthenticated: false,
};
default:
return state
}
}
const [state, dispatch] = useReducer(loginReducer, initialState);
const LoginManagement = () => {
dispatch({ type: LOGIN_START })
setTimeout(() => {
if (
state.username === "Deva" &&
state.password === "12345"
) {
dispatch({ type: LOGIN_SUCCESS });
} else {
dispatch({
type: LOGIN_ERROR,
payload: "Invalid username or password",
});
}
}, 1000);
}
return (
<div>
<h2>Login Form</h2>
<input type="text" placeholder='Username' value={state.username} onChange={(e) => dispatch({ type: SET_USERNAME, payload: e.target.value })} />
<input type="password" placeholder='Password' value={state.password} onChange={(e) => dispatch({ type: SET_PASSWORD, payload: e.target.value })} />
<button onClick={LoginManagement}>Login</button>
<button
onClick={() => dispatch({ type: LOGOUT })}>Logout</button>
{state.loading && <p>Loading...</p>}
{state.error && <p>{state.error}</p>}
{state.isAuthenticated && (<p>Login Successful</p>
)}
</div>
)
}
export default Login;
OUTPUT :
SCENARIO QUESTION :
Why is useReducer suitable for complex state like a shopping cart?
✓ Shopping carts involve many actions:
• Add product
• Remove product
• Increase quantity
• Decrease quantity
• Clear cart
✓ useReducer keeps all cart logic in one place.
✓ Makes state updates predictable and easier to debug.
✓ Prevents complicated nested
Use stateupdates.
✓ Easier to maintain as the application grows.






Top comments (0)