Counter with useReducer+Flux 的な何か

後で振り返るように。

action&state

interface Action<ActionType> {
  type: ActionType;
  payload?: any;
}

enum CounterActionType {
  Increase,
  Decrease
}

interface CounterState {
  count: number;
}

type CounterAction = Action<CounterActionType>;
function reducer(state: CounterState, action: CounterAction): CounterState {
  switch (action.type) {
    case CounterActionType.Increase:
      return { count: state.count + 1 };
    case CounterActionType.Decrease:
      return { count: state.count - 1 };
  }
}

class ActionCreater {
  private readonly dispach: React.Dispatch<CounterAction>;

  constructor(dispach: React.Dispatch<CounterAction>) {
    this.dispach = dispach;
  }

  increase() {
    const action: CounterAction = { type: CounterActionType.Increase };
    this.dispach(action);
  }

  decrease() {
    const action: CounterAction = { type: CounterActionType.Decrease };
    this.dispach(action);
  }
}

View

interface CounterViewProps {
  count: number;
  increase: () => void;
  decrease: () => void;
}

const CounterView: React.FC<CounterViewProps> = props => (
  <div>
    <p>Count: {props.count} </p>
    <button onClick={() => props.decrease()}>-</button>
    <button onClick={() => props.increase()}>+</button>
  </div>
);
import React, { useReducer } from 'react';

function CounterPage(): any {
  const initialState: CounterState = { count: 0 };
  const [state, dispach] = useReducer(reducer, initialState);
  const actionCreater = new ActionCreater(dispach);

  return (
    <CounterView
      count={state.count}
      increase={() => actionCreater.increase()}
      decrease={() => actionCreater.decrease()}
    />
  );
}

export default CounterPage;