useReducer keskittää tilasiirtymät yhteen puhtaaseen reducer-funktioon, sen sijaan että hajoittaisit ne moniin useState settereihin. Se on Reactin sisäänrakennettu versio Redux-mallista.
jsx
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "setStep": return { ...state, step: action.payload };
case "reset": return { count: 0, step: 1 };
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0, step: 1 });
// describe WHAT happened, not HOW state changes:
return <button onClick={() => dispatch({ type: "increment" })}>{state.count}</button>;
}
Kuinka se toimii
Käytät dispatch-funktiota lähettämään actionin (tavallinen objekti, joka kuvaa tapahtumaa). React kutsuu reducer(currentState, action) -funktiota ja käyttää palautetun objektin uutena tilana. Reducer on puhdas (ei sivuvaikutuksia, ei mutaatiota), mikä tekee logiikasta ennustettavan ja yksikkötestattavan eristyksissä.
Milloin se on parempi vaihtoehto kuin useState
- Seuraava tila riippuu edellisestä tilasta ei-triviaaleilla tavoilla.
- Useat arvot muuttuvat yhdessä (esim.
count+step+error). - Päivityslogiikka on niin monimutkainen, että toisintaisit sen eri käsittelijöissä.
jsx
// instead of 4 separate useState + 6 setters, one reducer owns it all
Bonus: dispatch sillä on vakaa identiteetti, joten sen välittäminen kontekstin kautta tai memoitettuihin alaisuuksiin ei aiheuta uudelleenrenderöintejä. Yksinkertaisten, riippumattomien arvojen kohdalla tavallinen useState on silti selkeämpi.
