Eslint-plugin-react: No Warning with function uses 'this', but it is missing in constructor

Created on 14 Dec 2018  路  8Comments  路  Source: yannickcr/eslint-plugin-react

My apologies if this was addressed already, but I could not find it or if it is something that should go to the main eslint library, please let me know. I will try to explain it as clearly as I can.

We work with a lot of parent and children components that also have many children under them. Thus the parent component can get quite complex when it is handling all the state for the application's screen and its children. A side affect of this, is that the constructor can get quite large and over sights can be made where it takes awhile to figure out what is going on.

We will get this message "Uncaught TypeError: Cannot read property 'props' of null" if/when we introduce the "this" into a function but haven't put it into the constructor of the parent component. There appears to be no eslint rule for this, and while you do get a TypeError, it isn't the greatest to point you to the constructor as a possible culprit.

_A very simple (not complete) example is below:_

Parent Component:

import ChildComponent from '/ChildComponent.jsx';
class AddPeople extends Component {
  constructor(props) {
      super(props); // EDIT: this makes no difference for a function below that is using 'this', but is not listed here.
      this.closeModal = this.closeModal.bind(this);
      // NOTE: MISSING the openModal function here which throws the error above in the console.
      this.state = {
        open_close: false
      }
  }

openModal() {  /* NOTE: this one is not up in the constructor, thus throws the TypeError. 
     Do something with props here like a query or something....
     console.log(this.props); // ERROR
     this.setState({
        open_close: true
     })
  }

  closeModal() {
     this.setState({
        open_close: false
     })
  }
  render () {
     <ChildComponent {...this.state} closeModal={this.closeModal}  openModal={this.openModal}
  }
}

ChildComponent

import {Modal, Alert} from 'react-bootstrap';
class ChildComponent extends Component {

    render() {
        <a onClick={this.props.openModal}>Open Modal</a>
       <Modal show={this.props.open_close}  onHide={this.props.closeModal}>
....there is a bunch of things I left out here to make modal work like <Modal.Header>
       </Modal>
    }
}

Thank you for your consideration.

question

All 8 comments

A constructor for a React Component has to call super(props) for this to work properly.

^ I thought this was only necessary for this.props to work properly in the constructor. Not saying one shouldn't call super(props) though.

@alexzherdev it's necessary for any use of this, and it'll throw an error if you attempt to reference this before calling super().

Ah, I think I confused that with forgetting to pass props into super(). Thanks.

Thank you for your comments, however in the scenario super props was called and the error still throw. The issue is that the function itself was left out of the constructor and eslint did not pick that up when the function uses 'this' keyword. I will adjust the example above.

ah - so the issue is that you forgot to bind the instance method.

I鈥檓 not sure if this is really something that can be reliably caught with linting, as opposed to with unit tests.

@ljharb - exactly. :) Yeah I was moving code around and deleted the method from the constructor - specifically the openModal method. Because this.setState was in the method, the error popped. :(

Once I realized the code move was not going to work, I had to put the function back into the parent component - forgetting the one constructor line for the instance method.

I thought I would ask about the linting, because the error in the console was not the best. :)

(Separately, inheritance in React is a large antipattern; code should be shared via composition, not inheritance)

Was this page helpful?
0 / 5 - 0 ratings