The singular struggle I have with Redux toolkit is that so much happens in the createSlice function that needing to deviating from it a little feels like a whole new pattern to adopt.
It’s crystal clear how to write the foundation, but the hallmarks of a great pattern are that you know exactly how to / where to place every type of exception you run into long term.
Say we have a simple createSlice function:
const doSomething = CaseReducer = (state, action) => {
state.didSomething = true
}
const slice = createSlice({
name: 'mySlice',
reducers: { doSomething }
})
// some-other-file
slice.actions.doSomething()
If in the future, imagine this slice relies on an action from another slice (say a detail page needs to update the list page content) and we end up with a circular import. slice A imports slice B and slice B imports slice A.
How do we convert a slice action out of the helper and into its own file?
// my-shared-action.ts
// move the shared action to its own file. You will need to create its action and reducer which createSlice did automatically
const doSomething = createAction(
"mySlice/doSomething",
(myArg) => ({payload: myArg})
)
const doSomethingReducer: <CaseReducer> = (state, action) => {
state.didSomething = true
}
// sliceA.ts
const slice = createSlice({
name: 'mySlice',
reducers: { },
extraReducers: (builder) => {
builder.addCase(doSomething.toString(), doSomethingReducer)
}
})
// sliceB.ts
const slice = createSlice({
name: 'mySliceB',
reducers: { },
extraReducers: (builder) => {
builder.addCase(doSomething.toString(), doSomethingReducer)
}
})
See we convert the createSlice action+reducer into one created from scratch in another file my-shared-action.ts using createAction and a plain reducer function.
We then import that action/reducer into two different slices, and register their reducers in their respective extraReducers properties.