Alwaysblue
Alwaysblue

Reputation: 11830

Constructor props state vs simply state

I started learning React when we could simply use state and create object instead of using constructor(props){ super(props)

Now, I see many libraries where they are still using

class Master extends Component {
  constructor(props){
    super(props)

So my first question is if there is an advantage of using constructor (props) super(props) and then setting up state? instead of just creating state object?

Second question, I wanted to implement react-native-slowlog in the native app I am making.

Throughout the code I have created the state object directly instead of using constructor.

The documentation for the react-native-slowlog shows this way to use it

class Master extends Component {
  constructor(props){
    super(props)
    slowlog(this, /.*/)

    this.state = this.getDataSource(props)
    this.shouldComponentUpdate = shouldComponentUpdate.bind(this)
  }
...
}

Where they call slowlog(this, /.*/) inside the constructor, so my question is can I avoid using constructor here? or is it okay if I create a constructor where I do slowlog(this, /.*/) and then create state object outside the constructor?

class Master extends Component {
  constructor(){
    super() 
    slowlog(this, /.*/)
  } 


  state = {
    searchCoin: false
  }

Upvotes: 4

Views: 1767

Answers (3)

kyle
kyle

Reputation: 2638

You only need to use the constructor if you are initializing state or binding functions.

If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component. https://reactjs.org/docs/react-component.html#constructor

So for what the library you linked to does, you do need to call it in the constructor. It both initializes the state and binds to the shouldComponentUpdate function.

However, if you aren't binding to anything you could always initialize the state directly on the property like this...

Typescript

class Master extends React.Component<any, any> {
  public readonly state = { someKey: "Initial Value" };
}

Javascript

class Master extends React.Component {
  state = { someKey: "Initial Value" };
}

Also I am not sure what the this.getDataSource(props) function does, and if that is just the example provided by slowlog. But initializing the state on the class property AND from the constructor won't wont. So you can do it like your example showed OR you could call that function from the componentDidMount function.

class Master extends React.Component {
  // initialize your state
  state = { someKey: "Initial Value" };

  constructor (props) {
    super(props)
    slowlog(this /*, */);

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

  componentDidMount() {
    const nextState = this.getDataSource(this.props);
    this.setState(nextState);
  }
}

On thing to note is that if getDataSource returns a promise, that should be called when the component mounts, rather than from the constructor.

If you need to load data from a remote endpoint, this is a good place to instantiate the network request. https://reactjs.org/docs/react-component.html#componentdidmount

Upvotes: 1

Yichz
Yichz

Reputation: 9671

  • Why uses constructor (props){} and super(props)?

The only reason is when you want to access this inside of the constructor React source code

if you pass:

class MyComponent extends React.Component {
     constructor(props) {
         super(props)

         console.log(this.props)
         // goood
     }
 }

if you are not passing but call super

 class MyComponent extends React.Component {
     constructor(props) {
         super()

         console.log(this.props)
         // -> undefined

         // Props parameter is still available
         console.log(props)
         // good
     }

     render() {
         // No difference outside constructor
         console.log(this.props)
         // good
     }
 }

if you dont call

class MyComponent extends React.Component {
     constructor(props) {
           console.log(this)
         // undefined
     }
 }

So in summary that is not always needed.

  • set state in constructor vs outside

That is just syntax sugar, therefore no difference.

constructor only get calls once per mount, so you want to do stuffs that you don't want to do on every render.

Upvotes: 5

Estus Flask
Estus Flask

Reputation: 222369

It's possible to skip explicit constructor if state is all you need to define, because this can be done with class fields proposal:

class Master extends Component {
  state = { searchCoin: false };
  ...

Which is syntactic sugar for ES6:

class Master extends Component {
  constructor(props){
    super(props);
    this.state = { searchCoin: false };
  } 
  ...

This is a matter of taste whether state is defined as class field or as a part of constructor body if there's a need for constructor; class field takes less characters to type because it doesn't contain this.

Also notice that

class Master extends Component {
  constructor(){
    super() 
    slowlog(this, /.*/)
  } 

  state = { searchCoin: false }
  ...

is syntactic sugar for

class Master extends Component {
  constructor(){
    super() 
    this.state = { searchCoin: false };
    slowlog(this, /.*/)
  } 
  ...

Class fields go after super and before other constructor statements. This may not work as intended if slowlog is expected to run first.

Upvotes: 3

Related Questions