реагирует на несколько действий в createSlice redux toolkit

#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.