Bug in last test - Write a Simple Counter

Tell us what’s happening:
There’s a bug with the last test. It fails unless the increment and decrement both are already working.

If you deliberately break your increment() or decrement() methods, it will cause your reset() method to also fail it’s test. The code below fails decrement() and reset(). But if you fix decrement() with this.setState({count: this.state.count - 1}), then all tests pass, without making any change to the reset() method.

Your code so far


class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    // change code below this line
    this.increment = this.increment.bind(this)
    this.decrement = this.decrement.bind(this)
    this.reset = this.reset.bind(this)
    // change code above this line
  }
  // change code below this line
  increment() {
    this.setState({count: this.state.count + 1})
  }

  decrement() {
    this.setState({count: this.state.count--})
  }

  reset() {
    this.setState({count: 0})
  }
  // change code above this line
  render() {
    return (
      <div>
        <button className='inc' onClick={this.increment}>Increment!</button>
        <button className='dec' onClick={this.decrement}>Decrement!</button>
        <button className='reset' onClick={this.reset}>Reset</button>
        <h1>Current Count: {this.state.count}</h1>
      </div>
    );
  }
};

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0.

Link to the challenge:
https://learn.freecodecamp.org/front-end-libraries/react/write-a-simple-counter

This is the issue.

count: this.state.count-- means set the count with this.state.count, and then decrease the this.state.count by one. So count never will be changed, and no render since there is no change with the state.

You should decrease it first, then assign it to state. either using
--this.state.count
or
this.state.count-1

It also passes the test too.

I’m not really expert about react to know how does it find when a state is changed.

I had one similar issue(I hope OP keeps the faulty code alive), but this is about array, which got new items on it. We realized the react here doesn’t go deep, and tend to check with object reference(pointer), and shallow copy to go for a new render, or better just state reference.

As You mentioned Mr. Dawson

If you change the decrease method to following(your point):

decrement() {
    this.state.count--;
    // this.setState({count: (this.state.count-1)})
    console.log(this.state);
  }

And try some decrease, you see no render.
Once there is a increment, sine increment creates a object, rather change the value of state, so render is triggered, and latest result is on.

this is what I think react looks for state reference, rather deep diff(or value(s) signature)(but shallow), but I think this is fair since state could be in any scheme, and checking properties and values to find the diff could be hard way.
I don’t know, but maybe there is some explicit way to force a new render, or primitive like state rather than object.(sorry for lack of knowledge)

Indeed You have more info about react than me, I just had around 5 min to understand how does it work, and found it’s event-based framework(still not sure).

You you are right, now I got it more clear, thank for informing. Really appreciate it.

I’m not sure if it’s possible to have delegate monitoring an object, and gets triggered when object state is changed, especially when type could be anything.

I’m thinking state is an especial thing about react, since react listen for setState(state_obj) and then actually try to change the inherited state, not sure, but I’m thinking this way.

Exactly, I suggest user may keep state and stuffs she/he need to render with something else, such as my_state, or my_data. And leave the state as a simple object, or better just an int value. Whenever user wants to push a render, just increment the state or change it with something else. e.g.

function setMy_data(obj_arg,force_render=true){
//set my_data with/using obj_arg
if(force_render){
this.setState({state:<<random_number>>});//causes render by react
}
}

I think this is a good practice. User has its own object, she/he uses that object in render function. Same for re-render and a new state, no a big object should be passed.

I have one study to make my sure(still not sure, maybe I missed something) that if react have a delegate to monitoring the state object at real time, I still think it’s not possible, unless the object fires anything, so I came up with following:

function inc_(ins,c){
// ins.setState({count:c});//explicitly change state, so react fires a render
ins.state.count=c;//directly change state
console.log("inc_: "+c);
c++;
setTimeout(function(){inc_(ins,c);},1024);
}

and

constructor(props) {
    super(props);
   ...
    inc_(this,1);
  }

I think accessing the state directly won’t make any issue for reat, and I think this is more like your statement as

I think this is fair and logical. react comes with a API and way for coding. It supposed to do a render when user calls the setState, and (maybe with some shallow object state check).

I guess I need to reiterate the following:

If you deliberately break your increment() or decrement() methods, it will cause your reset() method to also fail it’s test. The code below fails decrement() and reset(). But if you fix decrement() with this.setState({count: this.state.count - 1}), then all tests pass, without making any change to the reset() method.

I know why the decrement() test isn’t passing, I was just experimenting to see what is permissible and what wasn’t. That’s not the issue. The issue is that when initially trying to solve the problem, one might have the reset() function coded correctly but it reporting a failure because of the other tests that are linked to it. This could result in debugging the simpler reset() function first, even though it is already correct, causing wasted time and frustration.

This is becasue the reset is dependent on increment and decrement functions too, and I think this is logical and fair.

For example assume both increment and decrement are faulty(no state change), now either reset change it to zero or not, state is zero and test pass for reset which is wrong, becasue it expected zero and it is.

But the test first do some increment and keep values, then do some decrement and keep the results, and finally reset. So it expected something for instance 1, 2, 3, 2, 0 to make sure reset is working in real.

I think FCC should add some meta about the test for users to inform them some tests are dependent on other tests, so user would get informed if he/she needs change something failed the test or something else as dependant.

Edit:
I’m sorry I didn’t read your question clear, and didn’t understood it right, sorry, my bad. Thanks for reiterating, really appreciate it.