Idiomatic way to filter actions based on state when using builder? #2554
-
Hi, I am a longtime Redux user but only recently started using the toolkit. It's great. In old-style redux, sometimes I found it convenient to use state to filter out actions before my reducer processes an action. For example: const reducer = (state, action) => {
// short-circuit reducer here!
if (state.pause && action.type !== 'unpause') return state;
switch (action.type) {
case 'unpause': {
state.pause = true;
return state
}
// more cases...
}
} With the builder pattern, there's no way to intercept actions like this. I can see two ways to do it:
Is there something I am missing? Is middleware the right tool for the job here? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
I'm not entirely sure what the point of that "short-circuiting" is in the first place, tbh, even in the old style. Is that intended to be a "state machine"-ish approach, where you only care about action X if the reducer's state is already in a certain condition? (see the "Detailed Explanation" expander at https://redux.js.org/style-guide/#treat-reducers-as-state-machines for an example of what I mean.) If that really is what you want, then I can think of a couple ways to do something similar. First, inside of a given const mySlice = createSlice({
name,
initialState,
reducers: {
somethingHappened(state, action) {
if (!state.someStatus) return;
// now do actual update logic here
}
}
}) That works okay if there's only a couple cases that you might want to skip over, but if you've got a bunch of cases and want to potentially skip all of them, adding that check to the start of every case reducer would be tedious and annoying. If you really do want to skip all the cases depending on a state field, your best bet is to write a small wrapping reducer: const mySlice = createSlice({
name,
initialState,
reducers: {
somethingHappened(state, action) {
// actual update logic here
}
}
})
export const { somethingHappened } = mySlice.actions;
const mySliceReducerWithEarlyCheck = (state, action) => {
if (!state.someStatus) return;
return mySlice.reducer(state, action);
}
export default mySliceReducerWithEarlyCheck; |
Beta Was this translation helpful? Give feedback.
-
The idiomatic way would be to just put a if (state.pause) return at the start of all affected reducers. Sure, there might be more clever ways, but this is the one you will immediately understand when you come back 5 years later. |
Beta Was this translation helpful? Give feedback.
I'm not entirely sure what the point of that "short-circuiting" is in the first place, tbh, even in the old style. Is that intended to be a "state machine"-ish approach, where you only care about action X if the reducer's state is already in a certain condition? (see the "Detailed Explanation" expander at https://redux.js.org/style-guide/#treat-reducers-as-state-machines for an example of what I mean.)
If that really is what you want, then
createSlice
doesn't quite let you do that out of the box, because it's oriented around "handle this specific action type with this specific case reducer", and doesn't have a way to add some kind of a precondition in there.I can think of a couple ways t…