Help with Redux (action and state)

Tell us what’s happening:
Describe your issue in detail here.

  **Your code so far**

const defaultState = {
login: false
};

const reducer = (state = defaultState, action) => {
// Change code below this line
if (action.type === "LOGIN") {
  return {
    login: true
  }
} else {
  return {
    login: false
  }
}
// Change code above this line
};

const store = Redux.createStore(reducer);

const loginAction = () => {
return {
  type: 'LOGIN'
}
};
  **Your browser information:**

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?

Thanks.

but how does the function “knows” that state is “const defaultState”

This:

const reducer = (state = defaultState, action) => {

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.

1 Like

I think the else part should return the passed state

else {
  return state
}

We are not making any call to the login action in this code, but I believe it is assumed here that Redux is dispatching it for us.

1 Like

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.

1 Like

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 :neutral_face:).

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.

To quote from the Redux docs:

  • 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;

Or you can copy, modify, and return in one step:

if (action.type === "LOGIN") {
  return {
    ...state,
    login: true
  }

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.

Sorry, thanks for the correction. I shouldn’t say “update the state”. A better description may be “update the information by creating a new state?”

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.