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!