Understanding Constructors with React Components
Table of Contents
The constructor is a method that’s automatically called during the creation of an object from a class. It can handle your initial setup stuff like defaulting some properties of the object, or sanity checking the arguments that were passed in. Simply put, the constructor aids in constructing things.
In React, the constructor is no different. It can be used to bind event handlers to the component and/or initializing the local state of the component. The constructor()
method is fired before the component is mounted and like most things in React, has a few rules that you should follow when using them.
super(props)
before using this.props
>Call super(props)
before using this.props
#
Because of the nature of the constructor, right out of the gate the this.props
object is not available and can lead to bugs. This constructor would throw an error:
constructor() {
console.log(this.props);
}
Instead, we take a props
value from the constructor()
and pass it to the super()
method:
constructor(props) {
super(props);
console.log(this.props);
}
When you call the super()
method, it calls the constructor of the parent class which in the case of a React component is React.Component
.
setState()
inside constructor()
>Never call setState()
inside constructor()
#
The constructor of your component is the perfect place to set the initial state of your component. Instead of using setState()
like you would do in other methods in your class, you will need to set the initial state directly:
constructor(props) {
super(props);
this.state = {
reptile: 'alligator',
color: '#008f68',
};
}
The constructor is the only place that you should assign the local state directly like that. Any place else in our component, you should rely on setState()
instead.
this.props
to this.state
>Avoid assigning values from this.props
to this.state
#
When you’re setting your initial component state in the constructor, you should try to avoid setting values from the properties.
When you do something like this:
constructor(props) {
super(props);
this.state = {
reptile: props.reptile,
};
}
You would lose the ability to run setState()
later on and update the property.
Instead of assigning the property directly to the state, you can simply reference the property directly in your code by calling this.props.reptile
.
Bind events all in one place #
Not really a rule or gotcha, but worth noting that you can easily bind your event handlers in the constructor:
constructor(props) {
super(props);
this.state = {
// Sets that initial state
};
// Our event handlers
this.onClick = this.onClick.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
// et cetera...
}
constructor()
>Avoid using side-effects or subscriptions in constructor()
#
I get it, you just built a new component and you want it to pull data from an API and have it set the values to the state. It makes perfect sense to do this in the constructor, before the component mounts, right?
WRONG!
For things like subscriptions that will update the state and other side-effects, you should put the logic out in componentDidMount()
which will fire immediately after the component is mounted and won’t give you any trouble if you update the state inside of it.
Do you even need a constructor? #
The constructor comes in very handy, but sometimes it’s just too much. If you aren’t planning on maintaining state in your component and aren’t binding any event handlers, you don’t need to define a constructor at all.
In fact, if you don’t need state or event handlers, you probably don’t need a class-based component at all. You can save yourself a little bit of extra typing and simply use a functional component.