13

I am refactoring an es6 class based React component that uses the normal constructor, and then binds methods, and defines state/attributes within that constructor. Something like this:

class MySpecialComponent extends React.Component {
  constructor(props) {
   super(props)
   this.state = { thing: true }
   this.myMethod = this.myMethod.bind(this)
   this.myAttribute = { amazing: false }
  }

  myMethod(e) {
   this.setState({ thing: e.target.value })
  }
}

I want to refactor this so that I am autobinding the functions, and using property initializers for the state and attributes. Now my code looks something like this:

class MySpecialComponent extends React.Component {
  state = { thing: true }
  myAttribute = { amazing: false }


  myMethod = (e) => {
   this.setState({ thing: e.target.value })
  }
}

My question is, do I still need the constructor? Or are the props also autobound? I would have expected to still need the constructor and included super(props), but my code seems to be working and I'm confused.

Thanks

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Max Millington
  • 4,378
  • 4
  • 27
  • 34
  • 5
    If you don't define a constructor, the parent constructor is automatically called with the passed arguments. `constructor(...args) { super(...args); }` is basically the default constructor. – Felix Kling Jun 21 '17 at 19:16
  • If the component's state is dependent on its props, you would do the necessary initialization in the constructor. If the state is the same regardless of props, like is the case in your example, then you are good to go with what you wrote. – Ross Allen Jun 21 '17 at 19:35
  • Notice that all these things still happen inside the constructor, it's just different syntax. Which might be a bit confusing. Also, if you wanted to initialise your instance from argument values you would still need a `constructor` definition, but in react admittedly everything is thrown into the `props` object anyway. – Bergi Jun 21 '17 at 19:35

3 Answers3

12

From my understanding, you don't need to type out a constructor at all when using class properties (as in your second code example). The accepted answer states that you do need one if you "need to reference the props in your initial state object," but if you're using said class properties, then you're probably using Babel to transpile it, in which case a constructor is used, it's just being done behind the scenes. Because of this, you don't need to add a constructor yourself, even if you are using props in state.

See this aricle for better examples and a better explanation.

Christian Jensen
  • 900
  • 1
  • 10
  • 25
  • I'm sorry but can you explain this a bit more simply? Thanks – Ajay Gupta Jun 06 '19 at 06:21
  • The article I reference at the end does a great job at explaining it, but essentially, you don't need a constructor just because you are using props in the example the OP provided. Babel will add a constructor and call `super(props)` for you. – Christian Jensen Jun 06 '19 at 16:58
  • 1
    Okay. Thanks for that. So it means that, if I am not using Babel, etc. I will have to write a constructor, right? And just because I am using Babel, I am allowed to skip writing the constructor – Ajay Gupta Jun 07 '19 at 09:39
  • yes, I added similar answer https://stackoverflow.com/a/63109619/2761641 – Akshay Vijay Jain Jul 27 '20 at 07:43
8

You don't need an explicitly defined constructor unless you need to reference the props in your initial state object.

  • 6
    We could reference the `pops` in the initial state without constructor, right? Like: `state = { loopsRemaining: this.props.maxLoops, }` – Adam C. Dec 05 '17 at 14:51
  • 2
    @AdamC. is correct. Even if you need to reference props in your initial state object, you don't need a constructor. See [my answer](https://stackoverflow.com/questions/44684481/is-the-constructor-still-needed-in-react-with-autobinding-and-property-initializ/52064777#52064777) – Christian Jensen Jan 28 '19 at 15:19
2

You don't need to define a constructor explicitly , and then do super(props).You can access the props as in the example below. i.e. 'prop1'

class MySpecialComponent extends React.Component {
    state = { 
    thing: true ,
   prop1:this.props.prop1
  }
  myAttribute = { amazing: false }


 myMethod = (e) => {
  this.setState({ thing: e.target.value })
}


  render(){
  console.log(this.state.prop1);
   return(
       <div>Hi</div>
   );

   }
 }


 ReactDOM.render(<MySpecialComponent prop1={1}/> , mountNode);
Dhana
  • 694
  • 13
  • 18
  • But note that you don't need to assign a prop to a property on your state object, and in fact you [probably shouldn't](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state) – Christian Jensen Jan 28 '19 at 15:20