Writing a simple counter with redux

I’m not able to pass the test here what’s wrong in my code

  **Your code so far**

const INCREMENT = "INCREMENT"; // Define a constant for increment action types
const DECREMENT = "DECREMENT"; // Define a constant for decrement action types

const counterReducer = (count=0,action)=>{
if(action.todo=INCREMENT){
 return count+=1;
}
else if(action.todo=DECREMENT){
 return count-=1;
}
else{
  return count
}

} // Define the counter reducer which will increment or decrement the state based on the action it receives

const incAction = ()=>{
return{
todo:INCREMENT};
}; // Define an action creator for incrementing

const decAction = ()=>{
return{
todo:DECREMENT};
} // Define an action creator for decrementing

const store = Redux.createStore(counterReducer); // Define the Redux store here, passing in your reducers
  **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.124 Safari/537.36

Challenge: Write a Counter with Redux

Link to the challenge:

These two errors:

The action creator incAction should return an action object with type equal to the value of INCREMENT

Passed

The action creator decAction should return an action object with type equal to the value of DECREMENT

…and this is the relevant code:

const incAction = ()=>{
return{
action:INCREMENT};
}; // Define an action creator for incrementing

const decAction = ()=>{
return{
todo:DECREMENT};
} // Define an action creator for decrementing

Do you see the problem?


Your other issues are here:

const counterReducer = (count=0,action)=>{
if(action.todo=INCREMENT){
 return count+=1;
}
else if(action.todo=DECREMENT){
 return count-=1;
}
else{
  return count
}

} // Define the counter reducer which will increment or decrement the state based on the action it receives

First of all, there is a difference between = and == or ===. That is JS - sort that out.

Lastly, you are not supposed to mutate your state (which you are calling “count” here). The += operator changes the original.


When I fix those, your code passes for me.

Hi FranY4Real,

the initial state of your reducer should be an object. But in your case you just have an integer as initial state.

It is quite difficult to explain to you what I mean by that. So I guess in this case it is a good idea to provide you a brief code snippet that shall get you started:

const INCREMENT = "INCREMENT";

const initial_state = { counter: 0 }

const counterReducer = (state=initial_state, action) {
    
    switch(action.type) {
        case INCREMENT:
            return {
                ...state,
                // now you need to assign the new
                // value of your counter from action
                counter: action.counter_value
            }
        ...
    }
};


const incrementAction = (counter) => ({
    type: INCREMENT,
    counter_value: counter++
});

As you can see in the code snippet that I posted:

(1) our initial_state is a JavaScript object that contains a counter variable

(2) our counterReducer does not return a number. Instead, it all “old”
values of the state (we use the flat operator for this => ...state), and replaces
only the value of counter.

(3) Our incemrentAction supplies us with the new counter value (=> action.counter_value).

You need to understand that the reducers job is not to calculate the new counter value for the state.

The reducer is just here to take the new value of the counter and insert it at the correct place in our Redux state.

Redux is a framework which demonstrates an excellent separation of concerns. That is why we have these different components such as reducers and actions in the first place.

I hope this helps you, keep coding!

best
Dennis

Just to be clear, there is no reason why state must be an object. It is very common to have objects as the state of the leaves of your store, but it is perfectly fine to have primitives. Most of the projects on which I’ve worked had a few reducers that just used a primitive, if they only tracked one value. Of course, arrays and other reference types are allowed (OK, technically they’re objects, too…)

FCC has chosen to begin teaching this way, presumably because it is simpler and allows them to begin without getting people distracted worrying about the immutability of objects.

Ok, I did not know that FCC teaches Redux like that.

But let me ask: is there a reasonable scenario where you use a primitive for your Redux state?

That would imply that you use Redux to store a single primitive value which is not really that useful.

Or do I miss anything?

best
Dennis

Not for the whole state of the store, but each individual reducer function represents a slice of state, and it isn’t uncommon for some specific piece of state to just be a single value.

2 Likes

First of all, that is also how Redux teaches it, with the state as a primitive.

But let me ask: is there a reasonable scenario where you use a primitive for your Redux state?

Sure. For the entire Redux state? No, not really. It’s possible, but doesn’t seem that useful.

But of course, most Redux uses doesn’t have just one root reducer, they have a tree of reducers, with combineReducers at the nodes and a “pure” reducers at the leaves. There are certainly use cases to have a primitive at the leaves. You could have state.user.isRegistered, where that last value is just a simple reducer with one value.

Is it wise? Meh. Personally I like to make it an object anyway just to allow for future expansion, but if I know it will always just be one value, sure, I guess.

Yeah, one of my beef’s with Redux is how liberally they use the word “state”. It can refer to the entire redux state (as in mapStateToProps) or it can refer to the state leaf (as in a reducer). Personally I wish that they’d avoided the word since it already has a meaning in React. I wish they’d used the word “store”. But oh well…

1 Like

Thanks Dan and kevin,

I think I finally got the idea. Your point was not that the complete Redux state is just a primitive.

You could write a reducer that deals only with a primitive as reducer state and then plug multiple of these reducers together with combineReducers.

Essentially, the combineReducers provides each specific reducer with the chunk of state that it is responsible for.

Thanks for pointing it out!

best
Dennis

1 Like

@kevinSmith thanks for your time.But still i am confused about what are you trying to say.
Can you please give me your full solution of this.

We don’t like to give full solutions - this is a teaching site.

Can you be specific about what is confusing you?

1 Like

can’t we use ‘todo’ property instead of ‘type’ property in action creator function because i am unable to pass the test until i use the property ‘type’.

What you send to the reducer is an “action” which redux defines as an object with at least one property called “type”. That is where you give the reducer the “type”. There might be a way to make it work otherwise, but in the same sense that you can use a chainsaw to open a can of beans, it may not be a good idea.

Your action creator should return a valid redux action, so it must be an object with a “type” property.

So, for your action creator:

const incAction = () => {
  return {
    action:INCREMENT
  };
}; // Define an action creator for incrementing

The redux standard is for that property to be “type”, not “action”. The entire thing is an “action” object - it doesn’t need an “action” prop. (You can pass in other properties - that will be covered later.)

So, in your reducer:

const counterReducer = (count=0,action) => {
  if (action.todo = INCREMENT) {
  // ...

You should not be looking at action.todo. What should it be? What prop(s) does the action have? If you are unsure, you can always put in console.log(action) before the if and see what the reducer is seeing. (Note that there will be some redux actions happening that look odd, like “@@redux/INIT” - ignore those, those are just redux doing its work behind the scenes - very normal.)

The other problem you have with that line is

if(action.todo=INCREMENT){

The = is the assignment operator. You want to do and equality check, not the same things.


See how far you can get with that info. If it still isn’t working, share where you are now so we can guide you.

1 Like

Thankyou @kevinSmith for the explanation.Test passes for me now.

1 Like