loading...

useReducer in TypeScript, strictly typed version

acro5piano profile image Kay Gosho ・1 min read

https://reactjs.org/docs/hooks-reference.html#usereducer

type Reducer<S, A extends Action<any, any>> = (s: S, a: A) => S

interface Action<T extends string, P = undefined> {
  type: T
  payload: P
}

type Actions = 
  | Action<'increment', { by: number }>
  | Action<'decrement', { by: number }>
  | Action<'reset', { to: number }>

const initialState = {
  count: 0,
}

const reducer: Reducer<typeof initialState, Actions>(state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + action.payload.by };
    case 'decrement':
      return { count: state.count - action.payload.by };
    case 'reset':
      return { count: action.payload.to };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'decrement', payload: { by: 1 })}>-</button>
      <button onClick={() => dispatch({ type: 'increment', payload: { by: 1 }})}>+</button>
      <button onClick={() => dispatch({ type: 'reset', payload: { to: 0 } })}>+</button>
    </>
  );
}

Posted on by:

Discussion

markdown guide