Same action triggering in multiple slices Redux-Toolkit

Viewed 1621

I seem to be missing something. I have the following setup:

projectSlice.js

import { createSlice } from '@reduxjs/toolkit'

const projectSlice = createSlice({
  name: 'projects',
  initialState: {
    list: {
      'project-1': {
        id,
        columnIds: [columnId1, columnId2, ...],
        ...
      }
    },
    order: [],
  },
  reducers: {
     ...
  },
  extraReducers: {
    'columns/createColumn': (state, action) => {
      // this never triggers
      const { payload: { projectId, column } = action
      state.list[projectId].columnIds.splice(0, 0, column.id)
    }
  }
})
export default projectSlice.reducer

columnSlice.js

import { createSlice } from '@reduxjs/toolkit'

const columnSlice = createSlice({
  name: 'columns',
  initialState: {},
  reducers: {
    createColumn(state, action) {
       ...
    }
  },
})
export const { createColumn } = columnSlice.actions
export default columnSlice.reducer

and store.js

import { configureStore } from '@reduxjs/toolkit'
import projectReducer from '../projectSlice'
import columnSlice from '../columnSlice'

const store = configureStore({
  reducer: {
    projects: projectReducer,
    columns: columnReducer,
  }
})

Now, from what I understand from the docs, extraReducer should be able to listen to other redux actions, and trigger the extraReducer action.

I simplified this example, but basically I have a slice for columns and a slice for projects, and whenever a column is created, I need to add that to the list of columns in the project slice. But the extraReducer is never triggering. Not really sure where to go from here.

EDIT

Forgot to include this before, the dispatch is triggered from a react component

Project.js

import { useDispatch } from 'react-redux'
import { createColumn } from '../../columnSlice'

export default function Project() {
  const dispatch = useDispatch()

  const handleClick = () => {
    dispatch(createColumn({...})
  }

  return (
    <button onClick={handleClick}>Click me</button>
  )
}

The dispatch only triggers for the columnSlice, not for projectSlice

An example is provided in this sandbox to illustrate the issue

1 Answers

You should export createColumn action creator from columnSlice.actions. Then you need to dispatch the action that createColumn created.

E.g.

columnSlice.ts:

import { createSlice } from '@reduxjs/toolkit';

const columnSlice = createSlice({
  name: 'columns',
  initialState: {},
  reducers: {
    createColumn(state, action) {
      console.log('[columnSlice]: ', action);
    },
  },
});


export const { createColumn } = columnSlice.actions;

export default columnSlice.reducer;

projectSlice.ts:

import { createSlice } from '@reduxjs/toolkit';

const projectSlice = createSlice({
  name: 'projects',
  initialState: {
    list: {
      'project-1': {
        id: 1,
        columnIds: [1, 2],
      },
    },
    order: [],
  },
  reducers: {},
  extraReducers: {
    'columns/createColumn': (state: any, action) => {
      console.log('[projectSlice]:', action);
    },
  },
});
export default projectSlice.reducer;

store.ts:

import projectReducer from './projectSlice';
import columnReducer, { createColumn } from './columnSlice';
import { configureStore } from '@reduxjs/toolkit';

const store = configureStore({
  reducer: {
    projects: projectReducer,
    columns: columnReducer,
  },
});

store.dispatch(createColumn({}));

Output in the console:

[projectSlice]: { type: 'columns/createColumn', payload: {} }
[columnSlice]:  { type: 'columns/createColumn', payload: {} }

As you can see, both reducers are triggered.

Related