useReduce
Both useState and useReducer allow you to do the same thing: store state, update state, state is reactive. Difference? you can encapsulate more stuff with useReducer.
0
state and action types
interface State {
count: number;
error: string | null;
}
interface Action {
type: "increment" | "decrement";
payload?: null;
}
Take in the state, take in the action, make a copy of the state
Based on the action, do the hokey pokey, like in actionFunction
return the updated copy of the state. Don't mutate the OG state.
Reducer function
function reducer(state: State, action: Action) {
const { type } = action;
switch (type) {
case "increment": {
const newCount = state.count + 1;
const hasError = newCount > 5;
return { ...state, count: hasError ? state.count : newCount, error: hasError ? "Maximum reached" : null };
}
case "decrement": {
const newCount = state.count - 1;
const hasError = newCount < 0;
return { ...state, count: hasError ? state.count : newCount, error: hasError ? "Minimum reached" : null };
}
default:
return state;
}
}
Component
function Page1() {
const [state, dispatch] = useReducer(reducer, { count: 0, error: null });
return (
<div>
{state.count}
{state.error && <p className="text-red-500">{state.error}</p>}
<div className="flex gap-8 border">
<button onClick={() => dispatch({ type: "increment" })}>increment</button>
<button onClick={() => dispatch({ type: "decrement" })}>decrement</button>
</div>
</div>
);
}