User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36
Challenge: Handle an Action in the Store
Link to the challenge:
Hi there.
So far I´ve completed this challenge but I still don’t get how this works.
I know reduce takes two arguments: state and action, but how does the function “knows” that state is “const defaultState” and action is “const loginAction”? In which part of the code is all that related? Or I understood this in the wrong way?
Because we are telling it here that if state is undefined, use defaultState. When the reducer is called for the first time, state is undefined so the default value gets used.
and action is “const loginAction”?
This is happening behind the scenes here. You have a function that returns an action (i.e., an object that has at least a “type” property). Normally you would have to do something like:
dispatch(loginAction());
That would use redux’s dispatch function to take that returned object and pump it into redux. Then the “magic of redux” will know to call the reducer(s) with that action object.
I think the else part should return the passed state
Yes, that is a good point - a reducer should return the current state if no action types are matched. I don’t think that is causing the test to fail here, but you are right, that would be the correct way to do it, usually as the default case in a switch statement. I don’t see many if/else chains in reducers, but I may have used one in a case like this where there is only one action type. But if you do you an if/else chain, then the final else should just return the current state.
Thank you, guys @kevinSmith@twotani, now I get it. The fact that was behind scenes was confusing me a little bit.
Essentially “return state” and “return login: false” do the same thing, don’t they? Is the first thing better practice? Is the way I did it like “hard-coding”? I understand that “return state” makes more sense, but I don´t know how wrong is the code I wrote (it passed the test ).
In general, you want to return the passed state, instead of creating a new state. It’s difficult to see from this example, but in a more general situation, you will have many reducers and each of them will go through the passed state. And the state could contain a lot of information. If a reducer is interested in the action, then it handles the action and updates the state, and the updated state is returned. If a reducer is not interested in the passed action, it simply returns (pass along) the state.
In general, you want to return the passed state, instead of creating a new state
If a reducer is interested in the action, then it handles the action and updates the state,…
I disagree with these statements. A fundamental principle of redux is that you never mutate state. Unless you are returning the current state unchanged (e.g., as the default action), you should ALWAYS create and return a NEW state object, never mutate it, or “update” it.
They [reducers] are not allowed to modify the existing state . Instead, they must make immutable updates , by copying the existing state and making changes to the copied values.
So, you either make a shallow copy of the prexisting state and change that copy:
if (action.type === "LOGIN") {
const newState = state.slice(); // or = { ...state }
newState.login = true;
return newState;
The OP doesn’t have ...state in his new object, but it’s a moot point since he only has one property in the state for that reducer. But it probably would be a good habit to get into. I tend to do the ...state automatically in all my reducer returns, unless it is the default case (where I return the current state) or if it is some kind of “clear” action where I set the next state to the default state.