0

I'm trying to follow some best practices in React and am wondering about the anatomy of a React Component when using ES6 classes and where to declare things, specifically variables or properties that the class or .js file is going to use.

I've been reading various answers here, and have figured a couple of things:

  1. Initializing properties directly on a class in ES6 is not possible, only methods can currently be declared in this way. Same rules stand in ES7 as well.

https://stackoverflow.com/a/38269333/4942980

  1. A function in the render method will be created each render which is a slight performance hit. It's also messy if you put them in the render

    ...prefer only putting functions within render that deal exclusively with rendering components and/or JSX (i.e. mapping over a prop, switch statements that conditionally load a proper component based on a prop, etc...). If the logic behind the function is heavy, I'll leave it out of render.

https://stackoverflow.com/a/41369330/4942980

https://stackoverflow.com/a/42645492/4942980

  1. Moreover, a constructor should only create and initialize a new instance. It should set up data structures and all instance-specific properties, but not execute any tasks.

https://stackoverflow.com/a/24686979/4942980

Does this mean all variables for the class, that aren't methods and don't belong in render belong in the class constructor?

My understanding is that this:

class Counter {
   constructor(){
     this.count = 0;
   }
}

Is the same as this:

class Counter {
   count = 0;
}

Source: https://stackoverflow.com/a/47960459/4942980

I've seen my friends write code like this:

let count = 0;

class Counter extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <span>{count}</span>
    )
  }
}

ReactDOM.render(<Counter />, document.getElementById("root"));

That is, they are used to declaring variables with let/const/var and declare the property (or variable in this case) outside of the class and then stick it in the class as needed, so the .js file is filled with variables and sometimes methods and then halfway down is the class that invokes them.

Coming from a more OO background, this seems to me to be wrong? Are they correct? Should all the properties go in the constructor or on the class (if they don't deal with rendering explicitly) or in the render method instead if they do? Or is it fine to declare with the variable keywords like let and then put them in the class, be it the constructor, render method, etc as needed using their scope? Is this more or less fine if it's one class per .js file?

Thank you!

Summer Developer
  • 2,056
  • 7
  • 31
  • 68

1 Answers1

0

Does this mean all variables for the class, that aren't methods and don't belong in render belong in the class constructor?

That would be true with native JS (in other words ES syntax that is standardized and supported in browsers) but with TypeScript you would use class properties (and you can do the same using Babel):

class Counter {
   count = 0;
}

This is a stage 3 ES proposal syntax. Given the fact almost everybody is using Babel or TypeScript with React I'm surprised that the idea of putting class properties and bound methods in the constructor is still so widely recommended, that's only necessary in old code. Personally I use TypeScript and almost never do that.

It's especially useful in TypeScript to declare class properties because that's how you define the class type itself (ie that count is a property of Counter). Otherwise you need to deal with type errors:

class Counter {
  constructor() {
    this.count = 3; // Error: Property 'count' does not exist on type 'Counter'.
  }
}

I've seen my friends write code like this:

let count = 0;

class Counter extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <span>{count}</span>
    )
  }
}

That is, they are used to declaring variables with let/const/var and declare the property (or variable in this case) outside of the class and then stick it in the class as needed

Yeah, that looks wrong.

That's defining a property in module scope (not class instance scope). Referencing stuff outside the component from render() is discouraged. You should try to keep your components pure (only render based on this.props and this.state).

Using let or const outside the class is roughly the same as declaring something as static on the class:

class Counter {
  static count = 0;
}

Every Counter will have access to the same shared Counter.count variable. There may be a use case for that, but it's rare in React in my experience.

Aaron Beall
  • 49,769
  • 26
  • 85
  • 103