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