React - Write a Simple Counter

Apparently, my code does not do anything:

Here is the console result:

" // running tests Clicking the increment button should increment the count by

1

. Clicking the decrement button should decrement the count by

1

. Clicking the reset button should reset the count to

0

. // tests completed"

  **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(state => ({
          increment: count++
  }));
}
decrement() {
  this.setState(state => ({
    decrement: count--
  }));
}
reset() {
  this.setState(state => ({
    reset: 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 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36

Challenge: React - Write a Simple Counter

Link to the challenge:

OK, there are a couple of issues here.

increment() {
  this.setState(state => ({
          increment: count++
  }));
}

What is the variable count? It doesn’t exist. There is a property on the state called that. It was initialized like this:

  this.state = {
    count: 0
  };

That sets the state to an object with 1 property called “count”. That is what we should be returning in our setState callback, and object with that shape. But you are returning this:

{
          increment: count++
  }

You are creating a new object with no property “count”, but now it has a property called “increment” and we are giving that a value of the variable count, which doesn’t exist so we throw an error. In the browser console:

ReferenceError: count is not defined
    at Counter.<anonymous> (<anonymous>:57:27)

A word about the increment operator (++). Firstly, you have put it after the variable so it would increment it after it evaluates it (not what you would want) but also one of the rules is that we should not mutate state - don’t actively change state. The way we change state is to give a new object to setState. We have to do a little math there, but don’t use anything that would change the variable it is using (which increment and decrement do).


So, look back at our original shape of state:

  {
    count: 0
  }

That’s what we need to return, except that we may need to replace that “0” with something.

For our increment and decrement handlers, we need to know what the current state is. True, we could just use this.state, but that can be problematic so notice that there is an argument called state that is being passed into our callback functions. That is how we can figure out what the current count is. If you are unsure, you can expand that function to log it out:

increment() {
  this.setState(state => {
    console.log('increment state is:', state)
    return {
       increment: count++
    }
  });
}

See if that helps. If not, check back and we’ll see if you get closer.

Don’t get frustrated, I remember struggling with this stuff - it’s weird at first.

What do I need to do to be able to use console.log in this code:

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(state => ({
    console.log('count state is:', state)
      count: state.count +1
    }));
  }
decrement() {
    this.setState(state => ({
      count: state.count-1
    }));
  }
reset() {
    this.setState(state => ({
      count: state.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>
    );
  }
};

you can’t write it inside an object! in an object you can have only the key: value syntax. You need to write it somewhere where it’s correct to write an expression

like, Kevin did, for example, using explicit return, instead of implicit

1 Like

I would also say that this:

  reset() {
    this.setState(state => ({
      count: state.count=0
    }));
  }

is not a good pattern.

You are trying to mutate state.count. I’m not sure if that state has the same reference as this.state, but it probably doesn’t, so really you’re mutating a parameter, which is usually a bad thing (making it not a pure function). It works by accident because state.count=0 mutates that but then the whole thing evaluates to whatever you assigned it to, in this case 0, so the whole thing evaluates to 0 which then gets set as the value that you are returning, that updates state. The point is that the state.count= part of that is not only a bad pattern but is completely unnecessary.