Predict the State: A Redux Reducer
What is the state after the three dispatches? Explain why.
const initialState = { foo: [1], switch: false };
function FooReducer(state = initialState, action) {
switch (action.type) {
case "SET_FOO":
return Object.assign({}, state, { foo: action.foo, switch: true });
case "PUSH_FOO":
return Object.assign({}, state, {
foo: [...state.foo, action.foo],
switch: !state.switch,
});
default:
return state;
}
}
dispatch({ type: "SET_FOO", foo: [1, 2] });
dispatch({ type: "PUSH_FOO", foo: 3 });
dispatch({ type: "PUSH_FOO", foo: 6 });Hints
Hint 1
Trace the reducer one action at a time: each case returns a new object built from the previous state.
Hint 2
Watch switch: the set makes it true, and each push flips it.
Solution
Show the approach
Answer: { foo: [1, 2, 3, 6], switch: true }
SET_FOO replaces foo with [1, 2] and sets switch to true. Each PUSH_FOO appends to a copy of foo and flips switch: false after the first push, true after the second.
Worth saying out loud
- Read case labels character by character. If a case were written
"SET FOO"while the actions use"SET_FOO", every action would fall through todefaultand the state would stay{ foo: [1], switch: false }— with no error anywhere. Object.assign({}, state, ...)and the spread both build a new object, which is what letsconnectoruseSelectornotice the change.- Action type constants (or Redux Toolkit's
createSlice) exist to make that typo impossible.