#reactjs #redux #redux-toolkit
#reactjs #redux #redux-toolkit
Вопрос:
Я занимаюсь рефакторингом своих редукторов, чтобы использовать redux-toolkit createSlice
. Теперь у меня есть редуктор, основанный на событиях, и иногда требуется аналогичное обновление состояния для разных действий. С исходным switch/case
утверждением это не было проблемой:
case ActionTypes.CREATION_CANCELLED:
case ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED:
case ActionTypes.MARKER_SELECTED:
return {...state, isCreating: false};
Возможно ли такое поведение с createSlice
помощью функции?
Комментарии:
1. Я не уверен, поддерживается ли это из коробки, но вы всегда можете создать вспомогательную функцию, которая принимает
state
и возвращает то же состояние, но с{isCreating: false}
и использовать эту функцию в нескольких местах.
Ответ №1:
Вы можете сделать это, используя extraReducers
нотацию «обратный вызов builder«. С помощью этой нотации вы создаете редуктор, добавляя обращения к builder
объекту. Первый аргумент builder.addMatcher
функции определяет, какие типы действий соответствуют этому случаю.
Если ваши действия имеют общий строковый формат, вы можете использовать сопоставители на основе строк, action.type.endsWith('/rejected')
которые обрабатывают все rejected
действия одинаково.
В противном случае вы можете определить свою собственную пользовательскую функцию сопоставления, которая принимает action
и возвращает a boolean
, независимо от того, совпадает это или нет.
Поскольку мы хотим сопоставить несколько типов действий, мы можем создать для этого помощник.
// helper function to match any actions in a provided list
// actions can be `string` types or redux-toolkit action creators
const isAnyOf = (...matchers: Array<string | { type: string }>) =>
( action: AnyAction ) =>
matchers.some((matcher) =>
typeof matcher === "string"
? matcher === action.type
: matcher.type === action.type
);
Мы можем использовать это с вашими существующими string
константами:
const slice = createSlice({
name: "some name",
initialState: {
someProp: [],
isCreating: false
},
reducers: {},
extraReducers: (builder) => {
return builder.addMatcher(
isAnyOf(
ActionTypes.CREATION_CANCELLED,
ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED,
ActionTypes.MARKER_SELECTED
),
(state, action) => {
state.isCreating = false;
}
);
}
});
Или с помощью Redux Toolkit action creators:
const creationCancelled = createAction("CREATION_CANCELLED");
const newMarkerInfoWindowClosed = createAction("NEW_MARKER_INFOWINDOW_CLOSED");
const markerSelected = createAction("MARKER_SELECTED");
const slice = createSlice({
name: "some name",
initialState: {
someProp: [],
isCreating: false
},
reducers: {},
extraReducers: (builder) => {
return builder.addMatcher(
isAnyOf(creationCancelled, newMarkerInfoWindowClosed, markerSelected),
(state, action) => {
state.isCreating = false;
}
);
}
});
Комментарии:
1.
isAnyOf
теперь фактически является частью redux-toolkit redux-toolkit.js.org/api/matching-utilities#isanyof Тем не менее, это не вспомогательные строки, как вы представили здесь 🙂2. Интересно, что раньше это был очень чистый код с удобочитаемостью, а теперь это не так. Я думал, что инструментарий Redux должен был упростить использование redux.