Stahhp With The Outdated React Techniques!
Tags: react, functional, javascript, tutorial
Published: 2020-08-20 13:54:25

As an admitted React acolyte, I've written almost nothing but function-based components for the last six months or so.  But I still have many thousands of LoC to my name in class-based components.  And I'm getting really tired of seeing people showing examples of class-based components - circa 2014 - and then using those hackneyed examples as putative "proof" that classes are inferior.

If you can't write a _modern_ example of what a class-based component should look like, then please don't purport to educate others in the matter.

To be absolutely clear, I'm not fighting "for" class-based components.  Switch to Hooks, if you like.  _I have._  But don't pull up ridiculous examples of class-based components as the basis for your comparison.
<br/><br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/j45mzgldm2dasp9rjgwd.jpg)
## The Suspect
Here's what I'm talking about.  I recently saw this exact example shown in another article on this site:

```javascript
class Counter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };

    this.increment = this.increment.bind(this);
  }

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

  render() {
    return (
      <div>
        <button onClick={this.increment}>add 1</button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}
```

As always seems to be the case, this hackneyed example is used as supposed evidence of the verbosity and complexity of class-based components.  Predictably, the next example shows the same component done with Hooks.  And of course, it's much shorter, and presumably easier, to learn.  

The problem is that the class-component shown above _is bogus_.  Here's why:
<br/><br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vdp1saj8jz4a6nkv0g10.jpg)
## Stop Binding Everything!
This was a necessary step when React was first introduced - _more than a half decade ago_.  It's not necessary anymore with modern JavaScript.  

Instead, we can declare our methods statically with the arrow syntax.  The revised example looks like this:

```javascript
class Counter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
  }

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

  render = () => {
    return (
      <div>
        <button onClick={this.increment}>add 1</button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}
```

[NOTE:  I realize that, even amongst those who declare their methods this way, they often declare the traditional `render` method as `render() {...}`.  I personally prefer to declare the `render` method in the same way that I declare the rest of my methods, so everything is consistent.]

You might be thinking that this isn't much of a change.  After all, I only eliminated a single LoC.  But there are key benefits to this approach:
<br/>

1. Modern JavaScript is becoming ever more replete with functions declared by arrow syntax.  Therefore, declaring the class "methods" (which are really just... _functions_) with this syntax is more modern, more idiomatic, and it keeps all of the code more consistent.<br/><br/>

1. This method removes the boilerplate we've grown numb to at the top of many old-timey class-based React components where all the functions are bound in the constructor.  It also avoids development blunders when you try to invoke a function and realize that you've forgotten to bind it in the constructor.  Removing boilerplate is almost always a _net-good_.<br/><br/>

1. Class functions declared in this way cannot be accidentally redefined at runtime.<br/><br/>

1. Removing bindings from the constructor clears the way for us to remove _other things_ from the constructor...<br/><br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sat917hrxyzbqvtov5be.jpg)
## Stop Constructing Everything!
When writing class-based components, there are definitely times when a constructor is necessary.  But those times are... rare.

Look, I get it.  Every React tutorial since 1963 has used constructors.  So it's understandable why this paradigm is still being flogged to death.  But a constructor (in a React component) is almost always confined to two purposes:
<br/>

1. Initializing state variables<br/>

1. Binding methods<br/><br/>

Well, we already removed the bindings from the constructor.  So that only leaves the initialization of the state variables.  But you almost never need to initialize those variables inside of a constructor.  You can simply _declare_ them as part of the `state` object.  Right at the top of your class body.  

```javascript
class Counter extends Component {
  state = { count: 0 };

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

  render = () => {
    return (
      <div>
        <button onClick={this.increment}>add 1</button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}
```

Look at that!  No bindings.  No constructor.  Just a clean, simple initialization of state.
<br/><br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/j6654c15otjgdoeqffo0.jpg)
## Stop Writing Needless Tomes!
I realize that this point is going to veer heavily into the touchy ground of coding _style_.  And believe me, there are many aspects of my code that I choose to make purposely verbose.  But if we really wanna compare apples-to-apples when it comes to class-based or function-based components, we should strive to write _both_ as succinctly as possible.  

For example, why does `increment()` have its own bracketed set of instructions _when there's only one line of code in the function_??  

(And yeah... I know there's an argument to be made that you pick one convention for your functions and you stick to it.  But if you _know_ that a given function will only ever do _one_ thing - with a _single line of code_, then it feels rather silly to me to keep buffeting that single line of code in brackets.  I find this especially important when you're trying to compare two programming paradigms _based on their putative verbosity and complexity_.)

So we can slim down our component like so:

```javascript
class Counter extends Component {
  state = { count: 0 };

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

  render = () => {
    return (
      <div>
        <button onClick={this.increment}>add 1</button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}
```

But we don't need to stop there.  

Class-based components often look a bit longer because they're required to have a `render()` function, which in turn, returns some form of JSX.  But it's quite common for a component's `render()` function to contain no other logic other than the `return` of the display values.  This means that, in many class-based components, the `render()` function can be slimmed down like this:

```javascript
class Counter extends Component {
  state = { count: 0 };

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

  render = () => (
    <div>
      <button onClick={this.increment}>add 1</button>
      <p>{this.state.count}</p>
    </div>
  );
}
```

Now compare _this_ example to the bloated code that was originally offered as a template for class-based components.  Quite a bit shorter, no??  And is it any harder to read?  Obviously, that's subjective, but I don't think so.  In fact, I feel it's _easier_ to read and to understand.
<br/><br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tvhw851yb18fxqc8zyqn.jpg)
## Stop Putting Your Thumb On The Scales!
If you haven't figured out by now, one of my pet peeves in tech is when someone tries to advocate for Solution X over Solution Y by presenting rigged or misleading information.  With certain lazy audiences, such an approach can help you "win" your argument.  But with any discerning listener, you'll end up discrediting your own case.

I can show you examples of royally-effed-up relational databases.  And then I could put those examples against carefully-organized NoSQL databases.  And to the uninitiated, it may seem that relational databases are Da Sux.  And NoSQL databases are Da Bomb.  But anyone who truly understands the issue will look at my rigged example and discard my argument.

As a React dev, I used React examples because A) that's a world I'm well familiar with, B) it was a React example in another article that sparked this response, and C) I've seen, first hand, how the perpetuation of these bad examples perpetuates their use in everyday code and skews legitimate debate about future React best practices.  

This article isn't about "class-based components are great" or "function-based components are stooopid".  In fact, I essentially _stopped_ writing class-based components altogether in favor of functions + Hooks.  

But if we're going to compare classes-vs-functions.  Or if we're going to compare _any_ solution vs _any other_ solution, at least take the time to gather clean examples.  Otherwise, it presents a warped version of the underlying reality.