I have individual users for which an enthusiasm value can be in/decremented. After this I want updated the overall enthusiasm level (globalEnthusiasmLevel) as wel, the sum of individual enthusiasm integers (per user).
I have everything I need to know to update the overall value at the time the individual value is being processed (action > reducer), however I want it to be a separate action for the sake of practice purposes.
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
and SET_GLOBAL_ENTHUSIASM
into a different reducer?1 - You can write a middleware to handle side-effect of action type INCREMENT_ENTHUSIASM
and DECREMENT_ENTHUSIASM
. Following example is written in ES6, so you would need to translate to 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)
);
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? It will be easier for you.
2 - If you intend to store globalEnthusiasmLevel
in a different reducer, then yes it should be. But see my point above about not storing but calculating it instead.