У меня есть отдельные пользователи, для которых значение энтузиазма может быть увеличено/уменьшено. После этого я хочу обновить общий уровень энтузиазма (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;
}
STORE_USERS и SET_GLOBAL_ENTHUSIASM на другой редуктор?




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 в другом редукторе, то да, так и должно быть. Но см. мое замечание выше о том, чтобы не хранить, а вычислять его.
о вашем замечании 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? >> правда, но это для практики и понимания.
@SanJayFalcon о вашем втором вопросе, это чисто личное предпочтение. Лично я буду нормализовать данные API до тех пор, пока они не станут плоскими, как таблицы БД, и создам редукторы для каждой «таблицы», то есть массива данных, и создам отдельные типы действий для каждого редуктора. Но у этого парня другое мнение, и я тоже считаю его правильным: stackoverflow.com/a/35494345/2404452. Итак, в конце концов, просто структурируйте свой магазин так, как вам удобно и имеет смысл.
@SanJayFalcon около 1 - поскольку я поставил next(action) первым, промежуточное программное обеспечение будет ждать, пока не будет выполнено 1-е действие, чтобы продолжить. Вы можете использовать промежуточное программное обеспечение, чтобы выполнить что-то раньше, изменить действие или завершить действие — настолько оно гибко.
очень обязан господин! очень полезно
1. это работает как шарм. Насколько я понимаю, функциональность промежуточного программного обеспечения выполняется ПОСЛЕ начального действия, верно? Таким образом, последний всегда работает с последним/текущим состоянием. 2. что здесь лучше всего? Например, я сохраняю пользователей, поступающих из бэкэнда, в том же редукторе (STORE_USERS). Это не кажется правильным, думаю, это должно быть отдельно?