I'm refactoring my reducers to use the redux-toolkit's createSlice
.
Now I have a very event-based reducer and sometimes a similar state update for different actions is required
.
With the original switch/case
statement this was no issue:
case ActionTypes.CREATION_CANCELLED:
case ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED:
case ActionTypes.MARKER_SELECTED:
return {...state, isCreating: false};
Is this kind of behaviour possible with a createSlice
function?
You can do this using the extraReducers
"builder callback" notation. With this notation you create a reducer by adding cases to a builder
object. The first argument of the builder.addMatcher
function determines which action types match this case.
If your actions share a common string format, you can use string-based matchers like action.type.endsWith('/rejected')
to handle all rejected
actions the same way.
Otherwise you can define your own custom matcher function that takes an action
and returns a boolean
of whether or not it's a match.
Since we want to match multiple action types, we can create a helper for that.
// helper function to match any actions in a provided list
// actions can be `string` types or redux-toolkit action creators
const isAnyOf = (...matchers: Array<string | { type: string }>) =>
( action: AnyAction ) =>
matchers.some((matcher) =>
typeof matcher === "string"
? matcher === action.type
: matcher.type === action.type
);
We can use this with your existing string
constants:
const slice = createSlice({
name: "some name",
initialState: {
someProp: [],
isCreating: false
},
reducers: {},
extraReducers: (builder) => {
return builder.addMatcher(
isAnyOf(
ActionTypes.CREATION_CANCELLED,
ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED,
ActionTypes.MARKER_SELECTED
),
(state, action) => {
state.isCreating = false;
}
);
}
});
Or with Redux Toolkit action creators:
const creationCancelled = createAction("CREATION_CANCELLED");
const newMarkerInfoWindowClosed = createAction("NEW_MARKER_INFOWINDOW_CLOSED");
const markerSelected = createAction("MARKER_SELECTED");
const slice = createSlice({
name: "some name",
initialState: {
someProp: [],
isCreating: false
},
reducers: {},
extraReducers: (builder) => {
return builder.addMatcher(
isAnyOf(creationCancelled, newMarkerInfoWindowClosed, markerSelected),
(state, action) => {
state.isCreating = false;
}
);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With