Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Counter with Context and useReducer
import React, { useReducer, createContext, useContext } from 'react';
type CounterProps = {
initialCount: number
};
type CounterState = {
count: number
};
type CounterAction = {
type: 'increment' | 'decrement' | 'reset',
payload?: number
};
function init (initialCount: number): CounterState {
return { count: initialCount };
}
function reducer (state: CounterState, action: CounterAction) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return init(action.payload as number);
default:
throw new Error();
}
}
const initialCount = 10;
type CounterContextProps = {
state: CounterState,
dispatch: React.Dispatch<CounterAction>
};
const contextStub: CounterContextProps = {
state: { count: 0 },
dispatch: () => { return; }
};
const CounterContext = createContext<CounterContextProps>(contextStub);
export function CounterProvider (props: React.PropsWithChildren<{}>) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<CounterContext.Provider value={{ state, dispatch }}>
{props.children}
</CounterContext.Provider>
);
}
export function Counter ({ initialCount }: CounterProps) {
const { state, dispatch } = useContext(CounterContext);
return (
<>
Count: { state.count }
<button onClick={() => dispatch({ type: 'reset', payload: initialCount })}>
Reset
</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.