Reputation: 5306
I would like two different slices to cross-reference each other's actions like so:
const sliceA = createSlice({
name: "sliceA",
initialState: null,
reducers: {
someReducer: (state, action) => {
// do something
},
},
extraReducers: {
[sliceB.actions.anotherReducer]: (state, action) => {
// do something
},
},
});
const sliceB = createSlice({
name: "sliceB",
initialState: null,
reducers: {
anotherReducer: (state, action) => {
// do something else
},
},
extraReducers: {
[sliceA.actions.someReducer]: (state, action) => {
// do something else
},
},
});
The problem is that I receive the error that sliceB is undefined when trying to set the extraReducers for sliceA.
I would like to keep the slices separate for clarity, but that some of their actions affect each other.
What is a good way to achieve that?
Upvotes: 7
Views: 5502
Reputation: 353
You have to resolve the circular dependency between the slices by factoring out the creation for the one of the actions into a createActions call that both createSlice calls can reference as extraReducers without their definition being circular.
also note your action naming, and then the line here, is misleading:
[sliceA.actions.someReducer]: (state, action) => {
You createSlice is making both actions and reducers, so use a name for the action that doesn't imply it's a reducer.
use createAction: https://redux-toolkit.js.org/api/createAction
See circular ref notes here: https://redux-toolkit.js.org/usage/usage-guide#exporting-and-using-slices
const actionOnAThatAffectsB = createAction('B_ACTION_NAME', function prepare(text) {
// this function is an optional parameter to createAction.
// only use it if you want to add to the eventual payload.
return {
payload: {
text,
id: nanoid(),
createdAt: new Date().toISOString()
}
}
})
const sliceB = createSlice({
name: "sliceB",
initialState: null,
reducers: {
actionOnBThatAffectsA: (state, action) => {
// do main stuff on A
},
},
extraReducers: {
[sliceA.actions.someAction]: (state, action) => {
// do other stuff.
},
},
});
const sliceA = createSlice({
name: "sliceA",
initialState: null,
reducers: {},
extraReducers: {
[sliceB.actions.actionOnBThatAffectsA]: (state, action) => {
// do extra stuff on A
},
[actionOnAThatAffectsB]: (state, action) => {
// you can't create the *action* here with createSlice's default creation through the reducers{} parameter — since that leads to a circular reference during creation.
// You *are* creating the *reducer* itself here, though.
},
},
});
Upvotes: 6