3

I am trying to call a function from another function in my React app. But I keep this error: Error in login TypeError: Cannot read property 'loadDashboard' of undefined. I searched for similar cases all I could find was (1) That I have to use this keyword (2) I have to mention the function inside constructor. I have done both then why I keep getting the error??
My code:

import React, { Component } from 'react';
import '../App.css';
var axios = require('axios');

class Login extends Component {
  constructor(){
    super();
    this.loadDashboard = this.loadDashboard.bind(this);
  }

  loadDashboard(token){
    axios({
      method:'get',
      url:'http://localhost:3000/api/dashboard',
      data: {
        Authorization: token
      },
      responseType:'stream'
    })
     .then(function (response) {
       console.log(response);
     })
     .catch(function (error) {
       console.log("Error in loading Dashboard "+error);
     });
  }

  handleOnSubmit = () => {
     console.log("submittwed");
     axios({
       method:'post',
       url:'http://localhost:3000/authenticate',
       data: {
         email: '[email protected]',
         password: 'apple'
       },
     })
      .then(function (response) {
        var token = response.data.auth_token;
        console.log(token);
        this.loadDashboard(token);
      })
      .catch(function (error) {
        console.log("Error in login "+error);
      });
   }

  render() {
    return (
      <div>
         Username: <input type="email" name="fname" /><br />
         Password: <input type="password" name="lname" /><br />
         <button onClick={this.handleOnSubmit}>LOG IN</button>
      </div>
    );
  }
}

export default Login;        

NOTE: Without loadDashboard, handleOnSubmit function works just fine.

Also, why changing loadDashboard(token){..} to function loadDashboard(token){..} gives me Unexpected token error?

4
  • 1
    this.loadDashboard = this.loadDashboard.bind(this); to this.loadDashboard = loadDashboard.bind(this); Commented Sep 11, 2017 at 11:50
  • "Also, why changing loadDashboard(token){..} to function loadDashboard(token){..} gives me Unexpected token error? " in objects, the foo() {} syntax is the shorthand for foo: function() {} therefor you don't have to use the function keyword in classes Commented Sep 11, 2017 at 11:52
  • @Nocebo doing that gives 'loadDashboard' is not defined no-undef in compilation. And the program halts. Commented Sep 11, 2017 at 11:54
  • you could do the this binding also for the handleOnSubmit method. handleOnSubmit () {} and in the constructor simliar to the laodDashboard: this.handleOnSubmit = this.handleOnSubmit.bind(this) Commented Sep 11, 2017 at 11:54

2 Answers 2

6

you could use the arrow function to have the correct this context in your callback:

.then((response) => {
    var token = response.data.auth_token;
    console.log(token);
    this.loadDashboard(token);
  })

You could also do something like this, but arrow function are way smoother:

axios.get("/yourURL").then(function(response) {
  this.setState({ events: response.data });
}.bind(this));
Sign up to request clarification or add additional context in comments.

3 Comments

Your solution worked. Thanks. I was following Axios official docs. They have used function (response){..} type of syntax here. Also can you please explain why that approach was wrong?
@mwCoder As the answer already briefly stated, if you use function () and try to access this within this callback this now refers to the callback function itself and not to the context of your component. You basically loose the context of this if you don't use arrow functions
you could probably look some online material regarding the arrow function and the lexical 'this' context. i give it a try. when you use the function keyword, then the function can accept a this context, namely with .call() or apply() axios propably does that.you could though generate a function which has a fixed context with .bind(yourThisContext) but when you use the arrow function, the this is the value of the enclosing execution context .
3

The smoothest way is to use arrow functions whenever you define a function:

loadDashboard = (token) => {//Note the arrow function
    axios({
      method:'get',
      url:'http://localhost:3000/api/dashboard',
      data: {
        Authorization: token
      },
      responseType:'stream'
    })
     .then((response) => { //Note the arrow function
       console.log(response);
     })
     .catch((error) => {//Note the arrow function
       console.log("Error in loading Dashboard "+error);
     });
  }

This way you don't need to bind your functions in your constructor and don't loose the context of this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.