Close

July 25, 2018

React: The Second Form of setState

I had a simple enough problem to solve: Create a counter that increments, decrements, and resets in React.

Of course with people looking over my shoulder while I am coding I often don’t create things that I am particularly proud of, but generally I get working code.

Here is a slightly cleaned up version of what I came up with:

See the Pen Simple React Counter by Thomas Nicolosi (@teeehn) on CodePen.

It works, but surely it could be simpler and better with fewer lines of code. I thought I could focus on the handleClick method for improvement:

  
handleClick (action) {
    let newCount = this.state.count;
    switch (action) {
      case 'increment':
        newCount += 1;
        break;
      case 'decrement':
        newCount -= 1;
        break;
      default:
        newCount = 0;
        break;
    }
    this.setState({
      count: newCount
    });
  }

Yeah, that is pretty verbose. I probably don’t need that newCount variable and that switch statement logic seems like overkill.

Because this is a really simple and common example, with a quick search I was able to find some inspiration from a github comment. This prompted me to take a fresh look at the setState API in React.

I learned something which might already have been obvious to many other React developers, but was new to me: there exists a second form of setState which is tied to the React component life cycle. In particular:

React setState

The second form of React’s setState which accepts a function.

Once I saw this I realized that there was an opportunity to improve my solution, knocking out several lines of code and at the same time making it more flexible. Here’s is what I came up with using the form of setState which accepts a function and the previousState as an argument:

See the Pen Simpler React Counter by Thomas Nicolosi (@teeehn) on CodePen.

My improved handleClick method is simpler and also allows me to pass a variable increment:


  handleClick (increment) {
    this.setState((previousState) => {
      return {
        count: increment ? previousState.count + increment : 0
      }
    });
  }

Pretty cool I think!

While this might not be impressive to many, I was able to extract some new information by questioning my experience and assumptions. I had always used the form of setState where I would pass an object or an object and a call back. By going back and reviewing the fundamentals I was able to take a fresh look at what I was doing and as a result gained some valuable knowledge.

If someone recognizes a way I can improve this even further please let me know in the comments! Thanks for reading.