Public Class Fields saves sooo many keystrokes in React code

14 April 2017   0 comments   Javascript, ReactJS

https://tc39.github.io/proposal-class-public-fields/

Powered by Fusion×

tl;dr; I'm not a TC39 member and I barely understand half of what those heros are working on but there is one feature they're working on that really stands out, in my view, for React coders; Public Class Fields.

The Problem?

Very common pattern in React code is that have a component that has methods that are tied to DOM events (e.g. onClick) and often these methods need acess to this. The component's this. So you can reach things like this.state or this.setState().

You might have this in your code:

class App extends Component {
  state = {counter: 0}

  constructor() {
    super()

    // Like homework or situps; something you have to do :(
    this.incrementCounter = this.incrementCounter.bind(this) 
  }

  incrementCounter() {
    this.setState(ps => {
      return {counter: ps.counter + 1}
    })
  }

  render() {
    return (
      <div>
        <p>
          <button onClick={this.incrementCounter}>Increment</button>
        </p>
        <h1>{this.state.counter}</h1>
      </div>
    )
  }
}

Demo

If you don't bind the class method to this in the constructor, this will be undefined inside the class instance field incrementCounter. Buu!

Suppose you don't like having the word incrementCounter written in 4 placecs, you might opt for this shorthand notation where you create a new unnamed function inside the render function:

class App extends Component {
  state = {counter: 0}

  render() {
    return (
      <div>
        <p>
          <button onClick={() => {
            this.setState(ps => {
              return {counter: ps.counter + 1}
            })
          }}>Increment</button>
        </p>
        <h1>{this.state.counter}</h1>
      </div>
    )
  }
}

Demo

Sooo much shorter and kinda nice that the code can be so close in proximity to the actual onClick event definition.

But this notation has a horrible side-effect. It creates a new function on every render. If instead of a regular DOM jsx object <button> it might be a sub-component like <CoolButton/> then that sub-component would be forced to re-render every time (unless you write your own shouldComponentUpdate.

Also, this notation works when the code is small and light but it might get messy quickly if you need that functionality on other element's onClick. Or it might become mess with really deep indentation.

The Solution?

Public Class Fields.

That new feature is currently in the "Draft" stage at TC39. Aka. stage 1.

However, I discovered that you can use stage-2 in Babel to use this particular feature.

Note! I don't understand why you only have to put on your stage-2-brave socks for this feature when it's part of a definition that is stage 1.

Anyway, what it means is that you can define your field (aka method) like this instead:

class App extends Component {
  state = {counter: 0}

  incrementCounter = () => {
    this.setState(ps => {
      return {counter: ps.counter + 1}
    })
  }

  render() {
    return (
      <div>
        <p>
          <button onClick={this.incrementCounter}>Increment</button>
        </p>
        <h1>{this.state.counter}</h1>
      </div>
    )
  }
}

Demo

Now it's only mentioned by name incrementCounter twice. And no need for that manual binding in a constructor.
And since it's automatically bound, the function isn't recreated and those can easily make sub-components be pure.

So, let's always write our React methods this way from now on.

Oh, and in case you wonder. Inheritence works the same with these public class fields as the regular class instance fields.

Comments

Thank you for posting a comment

Your email will never ever be published


Related posts

Previous:
A decent Elasticsearch search engine implementation 09 April 2017
Next:
Best practice with retries with requests 19 April 2017
Related by Keyword:
Don't that this or bind 12 April 2016
Newfound love of @staticmethod in Python 02 July 2012
Related by Text:
4 different kinds of React component styles 07 April 2016
How to "onchange" in ReactJS 21 October 2015
Some tips on learning React 04 August 2015
maxlength_countdown() - a useful jQuery plugin for showing characters left 01 May 2011