Действие отправки после действия

У меня есть отдельные пользователи, для которых значение энтузиазма может быть уменьшено / уменьшено. После этого я хочу обновить общий уровень энтузиазма (globalEnthusiasmLevel), а также сумму индивидуальных целых чисел энтузиазма (на пользователя).

У меня есть все, что мне нужно знать, чтобы обновить общее значение во время обработки отдельного значения (действие> редуктор), однако я хочу, чтобы это было отдельным действием для практических целей.

export function enthusiasm(state: StoreState, action: UsersAction): StoreState {

  let globalEnthusiasmLevel: number;

  switch (action.type) {

    case INCREMENT_ENTHUSIASM:

      state.users = state.users.map((user: UserType) => {

        if (user._id === action.payload._id) {
          user.enthusiasmLevel = user.enthusiasmLevel + 1;
        }

        return user;
      });

      globalEnthusiasmLevel = state.globalEnthusiasmLevel + 1;
      return { ...state, globalEnthusiasmLevel };

    case DECREMENT_ENTHUSIASM:

      const users: UserType[] = state.users.map((user: UserType) => {

        if (user._id === action.payload._id) {
          globalEnthusiasmLevel = (user.enthusiasmLevel > 0 ) ? state.globalEnthusiasmLevel - 1 : state.globalEnthusiasmLevel;

          user.enthusiasmLevel = user.enthusiasmLevel - 1;
          user.enthusiasmLevel = Math.max(0, user.enthusiasmLevel);
        }

        return user;
      });

      return { ...state, ...users, globalEnthusiasmLevel };

    case STORE_USERS:
      return { ...state, users: action.payload };

    case SET_GLOBAL_ENTHUSIASM:
      return { ...state, globalEnthusiasmLevel: action.payload };

    default:
      return state;
  } 
  1. Что было бы наилучшим подходом к отправке действия после акиона?
  2. разумно ли разделить STORE_USERS и SET_GLOBAL_ENTHUSIASM в другой редуктор?

person San Jay Falcon    schedule 30.04.2019    source источник


Ответы (1)


1. Вы можете написать промежуточное ПО для обработки побочных эффектов типа действия INCREMENT_ENTHUSIASM и DECREMENT_ENTHUSIASM. Следующий пример написан на ES6, поэтому вам нужно будет перевести его на Typescript.

const middleware = store => next => action => {
  next(action);
  switch (action.type) {
    case INCREMENT_ENTHUSIASM:
      store.dispatch({
        type: INCREMENT_GLOBAL_ENTHUSIASM // increment global value
      });
      break;
    case DECREMENT_ENTHUSIASM:
      store.dispatch({
        type: DECREMENT_GLOBAL_ENTHUSIASM // decrement global value
      });
      break;
    default:
      break;
  }
}

...
import { createStore, combineReducers, applyMiddleware } from 'redux';

const store = createStore(
  combineReducers({
    enthusiasm
  }),
  applyMiddleware(middleware)
);

Но если globalEnthusiasmLevel можно рассчитать по уровням энтузиазма всех пользователей, то как насчет того, чтобы не хранить их в магазине, а вычислить в mapStateToProps, когда вам нужно вместо этого использовать компонент React? Вам будет легче.

2 - Если вы собираетесь хранить globalEnthusiasmLevel в другом редукторе, то да, это должно быть. Но см. Мою точку зрения выше о том, чтобы не хранить, а вместо этого вычислять.

person blaz    schedule 30.04.2019
comment
1. это работает как шарм. Насколько я понимаю, функциональность промежуточного программного обеспечения выполняется ПОСЛЕ первоначального действия, верно? Таким образом, последний всегда работает с последним / текущим состоянием. 2. Какая здесь лучшая практика? Например, я сохраняю пользователей, приходящих из бэкэнда, в том же редукторе (STORE_USERS). Это не кажется правильным, думаю, это должно быть отделено? - person San Jay Falcon; 30.04.2019
comment
по поводу вашего замечания But if globalEnthusiasmLevel can be calculated from all users' enthusiasm levels, then how about not storing them in store, but calculated it in mapStateToProps when you need to use in React component instead? ›› верно, но это сделано для практики и понимания. - person San Jay Falcon; 30.04.2019
comment
@SanJayFalcon о вашем втором вопросе, это чисто личное предпочтение imo. Лично я буду нормализовать данные API до тех пор, пока они не станут плоскими, как таблицы БД, и буду создавать редукторы для каждой таблицы, то есть массива данных, и создавать отдельные типы действий для каждого редуктора. Но у этого парня другое мнение, и я считаю его верным: stackoverflow.com/a/35494345/2404452. В конце концов, просто структурируйте свой магазин так, как вы считаете его удобным и понятным. - person blaz; 30.04.2019
comment
@SanJayFalcon около 1 - поскольку я сначала поставил next(action), промежуточное ПО будет ждать, пока не будет выполнено 1-е действие, чтобы продолжить. Вы можете использовать промежуточное ПО для выполнения чего-либо раньше, изменения действия или прекращения действия - это настолько гибко. - person blaz; 30.04.2019
comment
Вам очень признателен, господин! очень полезно - person San Jay Falcon; 01.05.2019