Follow Redux

Tsynringe + reflect-decorator 를 활용해서 Redux와 비슷한 단일 스토어 상태관리 도구를 만들어 보자.

Base Store

/* eslint-disable no-underscore-dangle */
export type Action<P = unknown> = {
  type: string;
  payload?: P;
};

export type Reducer<S, P> = (state: S, action: Action<P>) => S;

export type Reducers<S, P> = Record<string, Reducer<S, P>>;

type Listener = () => void;

export default class BaseStore<S> {
  private listeners = new Set<Listener>();

  public reducer: Reducer<S, unknown>;

  // eslint-disable-next-line no-useless-constructor
  constructor(private _state: S, reducers: Reducers<S, any>) {
    this.reducer = (state: S, action: Action<unknown>) => {
      const reducer = Reflect.get(reducers, action.type);
      if (!reducer) {
        return state;
      }

      return reducer(state, action);
    };
  }

  get state() {
    return this._state;
  }

  dispatch(action: Action<unknown>) {
    this._state = this.reducer(this._state, action);
    this.publish();
  }

  protected publish() {
    this.listeners.forEach((listener) => listener());
  }

  addListener(listener: Listener) {
    this.listeners.add(listener);
  }

  removeListener(listener: Listener) {
    this.listeners.delete(listener);
  }
}

Store

useDispatch

useSelector

Usage

CounterController.tsx

Counter.tsx

Last updated