Tom
Tom

Reputation: 165

Share actions between slices with Redux Toolkit

How can I share common actions in redux state slices?

Say I want to share updateField defined below in multiple slices other than profile. Should I import it from external file?

I could use extraReducers from @redux/toolkit but then I should create a new slice containing my updateField action and that action don't have state of its own. It just use the state of the slice it's imported in.

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

export const INITIAL_STATE = { title: { value: '' } }

const slice = createSlice({
  name: 'profile',
  initialState: INITIAL_STATE,
  reducers: {

    updateField: (state, { payload: { name, value } }) => ({
      ...state,
      [name]: {
        ...state.data[name],
        value,
      },
    }),

  },
})

export const {
  updateField,
} = slice.actions

Thanks

Upvotes: 1

Views: 4618

Answers (2)

Drew Reese
Drew Reese

Reputation: 202605

If you are wanting to implement a single reducer function you can certainly define it once and export/import into the slices that need it.

Example:

export const updateField = (state, { payload: { name, value } }) => ({
  ...state,
  [name]: {
    ...state.data[name],
    value,
  },
})

Profile slice

import { createSlice } from '@reduxjs/toolkit';
import { updateField } from '../path/to/updateField'; // <-- import

export const INITIAL_STATE = { title: { value: '' } }

const slice = createSlice({
  name: 'profile',
  initialState: INITIAL_STATE,
  reducers: {
    updateField, // <-- pass to reducers object
  },
});

User slice

import { createSlice } from '@reduxjs/toolkit';
import { updateField } from '../path/to/updateField'; // <-- import

export const INITIAL_STATE = { title: { value: '' } }

const slice = createSlice({
  name: 'user',
  initialState: INITIAL_STATE,
  reducers: {
    updateField, // <-- pass to reducers object
  },
});

Upvotes: 0

Asen Mitrev
Asen Mitrev

Reputation: 693

You can use the extraReducers property on createSlice to listen to custom actions.

// actions
export const incrementBy = createAction<number>('incrementBy')

// reducers

const counter1 = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    decrement: (state) => state - 1,
  },
  // "builder callback API"
  extraReducers: (builder) => {
    builder.addCase(incrementBy, (state, action) => {
      return state + action.payload
    })
  },
})

const counter2 = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    decrementByTwo: (state) => state - 2,
  },
  // "builder callback API"
  extraReducers: (builder) => {
    builder.addCase(incrementBy, (state, action) => {
      return state + action.payload
    })
  },
})

Upvotes: 5

Related Questions