Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: this is null in event handler

I have a LoginForm component. I want to check before submit, that both loginName and password is set. I tried with this code (a lot of stuff omitted):

class LoginForm extends Component {

  constructor() {
    super();

    this.state = {
      error: "",

      loginName: "",
      password: "",
      remember: true
    };
  }


  submit(e) {
    e.preventDefault();
    if(!this.state.loginName || !this.state.password) { //this is null
      this.setState({ error: "Fill in both fields" });
    } else {
      console.log("submitting form");
    }
  }

  render() {
    return (
      <div className="col-xs-12 col-sm-6 col-md-4">
        <form className="login" onSubmit={this.submit}>
          <button type="submit" className="btn btn-default">Sign in</button>
        </form>
      </div>
    );
  }
}

export default LoginForm;

however, i get a TypeError in the event handler, saying that this is null.

What should I be doing?

like image 408
Midiparse Avatar asked Nov 10 '15 13:11

Midiparse


3 Answers

You need set this for submit method because now this is undefined, for this operation you can use .bind

onSubmit={ this.submit.bind(this) }

Example

or you can use arrow function

onSubmit={ (e) => this.submit(e) }

Example

like image 154
Oleksandr T. Avatar answered Oct 09 '22 01:10

Oleksandr T.


React was binding callbacks to this for you before. But now it is gone, and you have to bind it yourself or make wrapper like

onSubmit={() => this.submit()}
like image 8
huston007 Avatar answered Oct 09 '22 02:10

huston007


You have not bound the this to your class; You can use ES6 class properties feature to get around the problem in the cleanest way; So all you need to do is:

   submit = (e) => {
      // some code here
   }

The arrow function will auto bind it; Much nicer than binding it in a constructor; the most important thing is never ever do it this way:

onSubmit={() => this.submit()}

This will create a function which is an object in javascript and it will take some memory and is now residing inside your redner function! which makes it so expensive. render function is part of the code that runs so many times and each time your submit function is also created and you will end up with some performance relates issues. So your code should be like:

class LoginForm extends Component {
  submit = (e) => {
    // some code here
  }

  render() {
    return (
        <form className="login" onSubmit={ this.submit }>
          <button type="submit" className="btn btn-default">Sign in</button>
        </form>
      );
    }
}

export default LoginForm;

Here you will not have the performance issue, also you will not have the binding issue and your code looks much nicer.

like image 3
Nesa Mouzehkesh Avatar answered Oct 09 '22 02:10

Nesa Mouzehkesh