You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.4 KiB
55 lines
1.4 KiB
import {
|
|
createContext,
|
|
Dispatch,
|
|
ReactNode,
|
|
useContext,
|
|
useReducer,
|
|
} from "react";
|
|
|
|
type State = { count: number };
|
|
type Action = { type: "INCREMENT" | "DECREMENT" };
|
|
|
|
const initialState: State = { count: 0 };
|
|
|
|
function counterReducer(state: State, action: Action): State {
|
|
switch (action.type) {
|
|
case "INCREMENT":
|
|
return { count: state.count + 1 };
|
|
case "DECREMENT":
|
|
return { count: state.count - 1 };
|
|
default:
|
|
throw new Error("Unhandled action");
|
|
}
|
|
}
|
|
|
|
const CounterStateContext = createContext<State | undefined>(undefined);
|
|
const CounterDispatchContext = createContext<Dispatch<Action> | undefined>(
|
|
undefined
|
|
);
|
|
|
|
export function CounterProvider({ children }: { children: ReactNode }) {
|
|
const [state, dispatch] = useReducer(counterReducer, initialState);
|
|
return (
|
|
<CounterStateContext.Provider value={state}>
|
|
<CounterDispatchContext.Provider value={dispatch}>
|
|
{children}
|
|
</CounterDispatchContext.Provider>
|
|
</CounterStateContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useCounterState() {
|
|
const context = useContext(CounterStateContext);
|
|
if (context === undefined)
|
|
throw new Error("useCounterState must be used within a CounterProvider");
|
|
|
|
return context;
|
|
}
|
|
|
|
export function useCounterDispatch() {
|
|
const context = useContext(CounterDispatchContext);
|
|
if (context === undefined)
|
|
throw new Error("useCounterDispatch must be used within a CounterProvider");
|
|
|
|
return context;
|
|
}
|
|
|