Совместное использование действий между срезами с помощью инструментария Redux

#javascript #reactjs #redux #redux-toolkit

Вопрос:

Как я могу совместно использовать общие действия в срезах состояний redux?

Скажем, я хочу поделиться updateField , определенным ниже, несколькими фрагментами, отличными от profile . Должен ли я импортировать его из внешнего файла?

Я мог бы использовать extraReducers from @redux/toolkit , но тогда я должен создать новый фрагмент, содержащий мое updateField действие, и это действие не имеет собственного состояния. Он просто использует состояние среза, в котором он импортирован.

 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
 

Спасибо

Комментарии:

1. Можете ли вы уточнить, в чем заключается общность? Распространена ли реализация функции редуктора, и вы просто хотите сделать свой код более СУХИМ ? Может быть, вы хотите, чтобы другие редукторы также обрабатывали profile/updateField тип действия?

2. @DrewReese Первый случай: я хочу поделиться реализацией функции, чтобы я мог позвонить profile/updateField user/updateField , и т. Д.

Ответ №1:

Если вы хотите реализовать одну функцию редуктора, вы, безусловно, можете определить ее один раз и экспортировать/импортировать в нужные срезы.

Пример:

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

Срез профиля

 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
  },
});
 

Пользовательский срез

 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
  },
});
 

Комментарии:

1. Да, но когда я export const { updateField } = slice.actions , я получил 'updateField' has already declared ошибку

2. @Tom, поэтому либо используйте другое имя при импорте, либо другое имя при экспорте. Другое имя при импорте проще, import { updateField as updateFieldReducer } from '../path/to/updateField'; а затем передайте в срез как updateField: updateFieldReducer .

Ответ №2:

Вы можете использовать extraReducers свойство вкл createSlice .для прослушивания пользовательских действий.

 // 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
    })
  },
})