Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: TypeError: Cannot read property 'setState' of undefined

Im noob with React and trying to create a login form. When the user enters correct login informations a rest api will return JWT token. However i cant find how to set the state "token" to be the value of the response. Still i can save the response.token to localstorage and it shows correctly. I think the "this" points to wrong function, but how could i get around this without breaking the logic? Any hints? Thanks

Login.js

import React from 'react';

import axios from 'axios';

import Glyphicon from 'react-bootstrap/lib/Glyphicon';

import MyInput from './../components/Input';

import { connect } from "react-redux";

import { Form } from 'formsy-react';

var server = "http://localhost:3000";

class Login extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            canSubmit: false,
            token: null
        };
        this.enableButton = this.enableButton.bind(this);
        this.disableButton = this.disableButton.bind(this);
        this.submit = this.submit.bind(this);
    }

    submit(data) {
        axios.post(server + '/login', {
            username: data.username,
            password: data.password
        })
            .then(function (response) {
                if (response.data.token) {
                    var token = response.data.token;
                    localStorage.setItem("token", token);
                    this.setState({ token: token }); //Here is the problem
                    console.log(this.state.token);
                } else {
                    location.reload();
                }
            });
    }

    enableButton() {
        this.setState({ canSubmit: true })
    }
    disableButton() {
        this.setState({ canSubmit: false })
    }

    render() {
        return (
            <div className="loginForm">
                <h2 className="page-header">Login</h2>
                <Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton}>
                    <div className="form-group">
                        <label>Username: </label>
                        <MyInput name="username" validations="isExisty" validationError="Required" required />
                    </div>
                    <div class="form-group">
                        <label>Password: </label>
                        <MyInput type="password" name="password" validations="isExisty" validationError="Required" required />
                    </div>
                    <button
                        type="submit"
                        className="btn btn-primary"
                        disabled={!this.state.canSubmit}>
                        Login
                    </button>
                </Form>
                <br/>
                <a href="register">Create user!</a>
                <a id="forgot" href="forgot">Forgot password?</a>

            </div>);
    }
}
export default Login;
like image 712
Jack M. Avatar asked Aug 25 '16 07:08

Jack M.


People also ask

Why cannot read property ‘setState’ of undefined ReactJS?

TypeError: Cannot read property 'setState' of undefined ReactJS The solution. The issue happens because the method is not properly bind with this. As we all know that when we create a function it has it’s own special object this. As the arrow function does not have any special object this.

How to fix “this setState is not a function” error in react?

Use the ES6 syntax for the big arrow function. It automatically binds the “this” keyword to that method so you don’t have to bind it in the constructor: There you have it! That’s how you get rid of the “this.setState” is “undefined” or “not a function” error when using the class component structure in React.

Why arrow function is not working in ReactJS?

The issue happens because the method is not properly bind with this. As we all know that when we create a function it has it’s own special object this. As the arrow function does not have any special object this. This problem can be solved with the arrow function like below: Here is a good article about bind of ReactJS component classes.

Why am I getting errors when calling a method in react?

These errors occur because the method you are using or invoking in your React Component is not bound correctly. Here is an example of code that will cause the error to happen (This assumes that you have your React component set up correctly):


2 Answers

You can use an arrow function to keep the context of submit and be able to access to setState:

submit(data) {
    axios.post(server + '/login', {
      username: data.username,
      password: data.password
    })
    .then((response) => {
        if (response.data.token) {
            var token = response.data.token;
            localStorage.setItem("token", token);
            this.setState({ token: token });
            console.log(this.state.token);
        } else {
            location.reload();
        }
    });
}
like image 105
Anthony Dugois Avatar answered Oct 09 '22 16:10

Anthony Dugois


As Alexander stated in the comment, I must use the arrow function => or set this for callback.

like image 20
Jack M. Avatar answered Oct 09 '22 15:10

Jack M.