Poznajemy optymalny sposób, aby napisać reducer function w TypeScript. Kontynuacja lekcji poprzednich. Do dzieła.

Ok, poprzednio ostro pojechaliśmy – enum z typami akcji, interfejsy dla każdego typu akcji z literalną wartością type i różnym payloadem, potem type reducerAction z unią tych interfejsów…

Koniec końców wyszło i do bardziej skomplikowanych problemów z pewnością się przydaje. Tutaj jednak pomyślmy o czymś łatwiejszym. Przykład z internetu i bardzo odpowiada mi to rozwiązanie.

Ok, najpierw init state:

import { useReducer } from "react";

const initialState = {
  counter: 100,
};

I teraz mega rzecz:

type ACTIONTYPES =
  | { type: "increment"; payload: number }
  | { type: "decrement"; payload: number };

To chyba najlepsze podejście możliwe. Piękne po prostu. A zarazem czytelne. Dobra, co tam dalej autor wymyślił:

function counterReducer(state: typeof initialState, action: ACTIONTYPES) {
  switch (action.type) {
    case "increment":
      return {
        ...state,
        counter: state.counter + action.payload,
      };
    case "decrement":
      return {
        ...state,
        counter: state.counter - action.payload,
      };
    default:
      throw new Error("Bad action");
  }
}

Ja bym jeszcze dodał, że zwraca typeof initialState, ale mniejsza. Niewiele więcej się tu da wymyślić, większość reducerów jest do siebie podobna, trzeba tylko poznać dobry patent i zrozumieć na tych łatwych przykładach te kilka konceptów, zanim zabierzemy się za pisanie własnych reducerów.

Chodzi o to, abyśmy nie wykładali się na najłatwiejszych kroczkach.

Jakby ktoś potrzebował, to tu ma komponent:

function UseReducerComponent() {
  const [state, dispatch] = useReducer(counterReducer, initialState);

  return (
    <div>
      <div>{state.counter}</div>
      <div>
        <button
          onClick={() =>
            dispatch({
              type: "increment",
              payload: 10,
            })
          }
        >
          Increment
        </button>{" "}
        |
        <button
          onClick={() =>
            dispatch({
              type: "decrement",
              payload: 5,
            })
          }
        >
          Decrement
        </button>
      </div>
    </div>
  );
}

export default UseReducerComponent;

Więcej Reacta i TSa niedługo!