I'm learning react from the docs, but not sure what the super() does in this example. Usually, doesn't it take the arguments that are passed to making a new instance and then calls React.Component's constructor method to incorporate these arguments into the instance? What does it do without any arguments?
class LikeButton extends React.Component {
constructor() {
super();
this.state = {
liked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({liked: !this.state.liked});
}
render() {
const text = this.state.liked ? 'liked' : 'haven\'t liked';
return (
<div onClick={this.handleClick}>
You {text} this. Click to toggle.
</div>
);
}
}
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
In ES6, derived classes have to call super() if they have a constructor. In react, all components extend from the Component class.
You don't actually need a constructor for every ES6/react class. If no custom constructor is defined, it will use the default constructor. For base classes, it is:
constructor() {}
And for derived classes, the default constructor is:
constructor(...args) {
super(...args);
}
You also need to call super() before accessing this, since this is not initialized until super() is called.
There are a few reasons to use a custom constructor in react. One is that you can set the initial state within the constructor using this.state = ... instead of using the getInitialState lifecycle method.
You can also bind class methods inside the constructor with this.someClassMethod = this.someClassMethod.bind(this). It's actually better to bind methods in the constructor since they will only be created once. Otherwise if you call bind or use arrow functions to bind methods anywhere outside the constructor (like in the render method), it will actually end up creating a new instance of the function on every render. Read more about that here.
If you want to use this.props in the constructor, you need to call super with props as an argument:
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
If you don't, then this.props is undefined in the constructor. However, you can still access this.props anywhere else in the class outside the constructor without needing to do anything with it in the constructor.
The super keyword in JavaScript is used in order to call the methods of the parent class. By itself, super() is used within a constructor function to call the parent constructor function. For example:
class Animal {
constructor(age) {
console.log('Animal being made');
this.age = age;
}
returnAge() {
return this.age;
}
}
class Dog extends Animal {
constructor (age){
super(age);
}
logAgeDog () {
console.log(`This dog is: ${ super.returnAge()} years old`);
}
}
const dog = new Dog(5);
console.log(dog);
dog.logAgeDog();
In this example we have a Dog class which extends an Animal class. The Dog class uses the super keyword twice. The first occurence is in the constructor, when super() is used in the constructor it will call the parent class constructor. Therefore we have to give the age property as an argument to it. Now the Dog successfully has an age property.
We can also use super outside of the constructor in order to access the parent's 'class' (i.e. prototype) properties and methods. We use this in the logAgeDog function located in the Dog class. We use the following code:
super.returnAge();
You should read this as:
Animal.returnAge(); // superClass.returnAge()
Why do I need this in React?
You need the super() keyword in React only when implementing a constructor. You have to do the following:
constructor(props) {
super(props);
// Don't call this.setState() here!
}
the parent class which is named Component needs to do some initialization on its own in order for React to work fine. If you implement a constructor without a super(props) call this.props in Component will be undefined which can lead to bugs.
Related
I am reviewing some React Js basics and I need some clarifications about the use of the constructor method within a react class based component. My normal practice is to declare a class based component and define state without using the constructor, like so:
import React, { Component } from 'react';
export class Testing extends Component {
state = {
example: "Hello World!!!"
}
render() {
return <div>
{this.state.example}
</div>;
}
}
export default Testing;
Since state is so easy to use without the (seemingly) pointless constructor, I began asking myself what the constructor was for. Just to clarify what I mean by the constructor, it is when you declare state like this instead of the above example:
constructor(props) {
super(props)
this.state = {
example: "Hello World!!!"
}
}
I found the suggestion in the react documentation that it is best practice to utilize the constructor, but it did not say why. After a little searching, I found a source that suggested that the constructor give you access to the props. I tested this and do see how the constructor gives access to props; however, the class can access props WITHOUT using the constructor, simply by stating this.props.myTest. I tested this as well by defining props in a parent component and drilling them down to the child component. I was able to access the props just fine with the this.props.myTest statement, no constructor necessary. So my question is, "What specifically does the constructor do, and when is it necessary (or is it ever necessary)?"
"when is the constructor necessary ?":
The constructor is not necessary, if you don't need it.
You might need a constructor e.g. if you need to bind a method to the class instance (so that this keeps pointing to the
class instance if you pass the function over to some other execution context):
export class Testing extends Component {
constructor( props ) {
super( props );
this.myMethod = this.myMethod.bind( this );
}
myMethod(){
console.log( this.props );
}
render() {
return <button onClick={ this.myMethod }>
click
</button>;
}
}
"What specifically does the constructor do" ?
A constructor "creates the instance" in javascript. So without a constructor, there would be no instance.
But also there is inherently always a constructor, even if you don't define one specifically.
You can define a constructor to overwrite the default constructor or to add some extra logic to be run
additionally to the super-constructor.
Accessing this.props in React
In javascript you could not access this.props without calling super(props).
Note that the constructor argument props and the instance property this.props are different "things".
Let's rename the constructor argument for now, to make it more obvious:
class SuperClass {
constructor( constructorArguments ) {
this.props = constructorArguments;
}
}
class DerivedClass extends SuperClass {
constructor( props ) {
super(); // <-- call the SuperClass constructor
}
method(){
console.log( this.props ); // <-- this.props is obviously never defined
}
}
const instance = new DerivedClass('some props');
instance.method();
But React "takes measures" to assign this.props anyway,
even when super(props) was never called.
But that happens later (after the constructor is done),
so you are able to access this.props in other methods later, but not inside the constructor:
export class Testing extends Component {
constructor( constructorArguments ) {
super(); // <-- super() is called without arguments
console.log( this.props ); // <-- this.props is undefined
}
render() {
console.log( this.props ); // <-- React sorted it out, now this.props is available
return null;
}
}
If you pass the constructor arguments to the super class constructor, then you can access this.props
inside the constructor:
constructor( constructorArguments ) {
super( constructorArguments ); // <-- super() is called with arguments
console.log( this.props ); // <-- this.props is available
}
React recommends to call super(props) anyway, to avoid introducing bugs with later changes.
I might add that it is very little extra code that doesn't do any harm.
Defining the state
class fields were not always available, so you had to define the state inside
the constructor, as the React example shows (like this.state = { value: 'value' }).
I personally think that it is probably ok now to use the class fields, but I always
tend to follow the official documentation, even if it might be outdated. There still
might be implications which I am not aware of.
See also: is-it-better-to-define-state-in-constructor-or-using-property-initializers
I understand the concept of constructors in OOP languages like C++. However, I am not entirely sure when to use a constructor in REACT. I do understand that JavaScript is object oriented, but I am not sure what the constructor is actually 'constructing'.
When rendering a child component, do you need a constructor in the child component? For example:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
error: null
}
}
render () {
return (
<React.Fragment>
<ChildComponent data={this.state.items}></ChildComponent>
</React.Fragment>
)
}
}
I will keep the example short for the sake of brevity. But, why would do you need a constructor? And would you need a constructor in the child component for props?
It is possible that my ES6 knowledge is not up to snuff.
If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.
The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
Typically, in React constructors are only used for two purposes:
Initializing local state by assigning an object to this.state.
Binding event handler methods to an instance.
https://reactjs.org/docs/react-component.html#constructor
A constructor function is NOT required at all.
State initialization can be done directly in the body of a class and function can be assigned to properties as described below, Technically these are known as class properties, it may land up soon in native javascript, yet because almost all of us use Babel transpiler for React projects, we can use that syntax
class Comp extends React.Component {
/*
* generally we do not need to put the props in state, but even if we need to.
* then it is accessible in this.props as shown below
**/
state={ first: 1, second: this.props.second }
handler= (token) => {
this.setState(prevState => ({first: prevState.first+1}));
}
render() {
return <div onClick={this.handler}>{this.state.first} and {this.state.second } </div>
}
}
Read more details about class properties and removing constructor from react class component over here.
https://hackernoon.com/the-constructor-is-dead-long-live-the-constructor-c10871bea599
Linke in your example, it's useful use constructor when you need to initialize your state, or bind some event-listener-function
<element onClick={this.handler} />
this.handler = this.bind.handler(this); inside the constructor
I want to know the conditions where by a constructor is not needed in a component's class declaration. I figure it is for stateless components, but are there any other reasons? Would not having any functions inside the component (besides life cycle functions) be one, for example?
I think it would be appropriate to just leave here an excerpt from react docs (emphasis mine):
The constructor is the right place to initialize state. If you don't
initialize state and you don't bind methods, you don't need to
implement a constructor for your React component.
I usually only add a constructor if the component has a internal state I need to set up before it is used, otherwise I leave out the constructor. Having functions in the component doesn't affect my decision in this regard
You don't actually need a constructor at all in any case if you use the babel stage-2 preset, because it provides the class properties that effectively replace its usage:
class Component extends React.Component {
constructor() {
this.state = {};
this.handleClick = this.handleClick.bind(this);
}
handleClick() { console.log('click'); }
}
becomes
class Component extends React.Component {
state = {};
handleClick = () => console.log('click');
}
Ignoring this, a constructor is needed only if you need to bind component methods to its context, or if you need to initialize the state property.
Another case is if you need to do something with the this.props class property, but this is considered an anti-pattern by React.
class Component extends React.Component {
constructor() {
this.state = {
// don't do this! anti-pattern! duplication of source of truth!
duplicatedState: this.props.myName,
};
}
}
Which is better (more performant), if one it is:
A:
class Man extends React.Component {
constructor(props) {
super(props)
this.talk = this.talk.bind(this)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={this.talk}>talk!</div>
}
}
B:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={this.talk.bind(this)}>talk!</div>
}
}
C:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={() => this.talk()}>talk!</div>
}
}
I think that calling the bind method directly in the render method could be negligible, but after all the render method is called ton of times. I want to understand if making a change in a big codebase is it worth it or not.
As per React DOC (last para of the page):
onClick={(e) => this.handleClick(e)} and onClick={this.talk.bind(this)}
The problem with this syntax is that a different callback is created
each time the component renders. In most cases, this is fine.
However, if this callback is passed as a prop to lower components,
those components might do an extra re-rendering. We generally
recommend binding in the constructor or using the property initializer
syntax, to avoid this sort of performance problem.
MDN DOC:
Function.prototype.bind():
The bind() method creates a new function always.
Binding method in the constructor:
However if you bind the method in the constructor:
this.handleClick = this.handleClick.bind(this);
and use it like this:
onClick={this.handleClick}
It will create only one instance and use that instance always. So binding method in the constructor means you end up binding only once and you can re-use it as many times, even if the render() method is called multiple times the same function will be used.
property initilizer syntax (this is experimental syntax.):
By this way you don't need to bind all the methods in the constructor, and it will not create multiple callbacks also.
handleClick = () => {
.....
}
The best solution will be auto binding internal methods. using arrow functions as methods.
So we don't rely on the constructor to bind the internal methods, and for example having multiple internal methods will just increase the number of lines of your files unnecessarily
Here is an implementation of what I'm saying:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {};
}
talk = () => { .. }
render () {
return <div onClick={this.talk}>talk!</div>
}
}
In order for this to work, you should use transform-class-properties from Babel Stage 2 preset
If we are to define 'more performant' as something that requires the least amount of computational resource, then option A (binding in the constructor) would be the most performant.
As you state, this is because this only happens once during the creation of an instance of the component. The .bind returns a newly bound function which is referenced later on.
The latter two options will be creating new functions (bound or anonymous) on every render, which is not necessary in this context.
I think you should do binding in constructor as calling bind returns a new function. It should be called one time for performance reasons. In you call it in render, bind will be called on every render and will return a new reference each time.
Learning React from the docs and came across this example:
class Square extends React.Component {
constructor() {
super();
this.state = {
value: null,
};
}
...
}
According to Mozilla, super allows you to use this in the constructor. Is there any other reason to use a standalone super (I know super allows you to access parent class's methods as well) but with React is there any other use case of just calling super() by itself?
super() will call the constructor of its parent class. This is required when you need to access some variables from the parent class.
In React, when you call super with props, React will make props available across the component through this.props. See example 2 below
without super()
class A {
constructor() {
this.a = 'hello'
}
}
class B extends A {
constructor(){
console.log(this.a) //throws an error
}
}
console.log(new B())
with super()
class A {
constructor(props) {
this.props = props
}
}
class B extends A {
constructor(props) {
super(props)
console.log(this.props)
}
}
console.log(new B({title: 'hello world'}))
super() is called inside a react component only if it has a constructor. For example, the below code doesn't require super:
class App extends React.component {
render(){
return <div>Hello { this.props.world }</div>;
}
}
However if we have a constructor then super() is mandatory:
class App extends React.component {
constructor(){
console.log(this) //Error: 'this' is not allowed before super()
}
}
The reason why this cannot be allowed before super() is because this is uninitialized if super() is not called. However even if we are not using this we need a super() inside a constructor because ES6 class constructors MUST call super if they are subclasses. Thus, you have to call super() as long as you have a constructor. (But a subclass does not have to have a constructor.)
We call super(props) inside the constructor if we have to use this.props, for example:
class App extends React.component{
constructor(props){
super(props);
console.log(this.props); // prints out whatever is inside props
}
}
I hope I could make it clear.
Worth adding that super() is short for superclass contructor, a concept from inheritance.
By default the class Square inherits the constructor from its superclass React.Component.
The inherited constructor can be overridden by declaring a new constructor() method.
If the intention is to extend rather than override the superclass constructor then it must be explicitly invoked using super().
When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
In JavaScript, super refers to the parent class constructor.
Importantly, you can’t use this in a constructor until after you’ve called the parent constructor. JavaScript won’t let you:
But we forgot that if a function is called before the super() call had a chance to set up this.name. So this.name isn’t even defined yet! As you can see, code like this can be very difficult to think about.
To avoid such pitfalls, JavaScript enforces that if you want to use this in a constructor, you have to call super first. Let the parent do its thing! And this limitation applies to React components defined as classes too:
super(); is not required by react, but is mandated by ES6 subclass
To use this keyword we should use the super keyword before it. Why? super is used to call the parent class's constructor.
Now why do we need to call the parent's constructor? The answer is to initialize the properties values which we are referring through this keyword.