0

I have pasted my whole there is very minor problem in this code but I'm not able to resolve the problem. Please review this code.

It's showing following error while consoling:

Uncaught TypeError: Cannot read property 'state' of undefined reactjs

Code:

export class Login extends Component {
  constructor(props) {
    super(props);
    this.handleChangeforSignUp = this.handleChangeforSignUp.bind(this);
    this.createNewUserWithEmailPassword = this.createNewUserWithEmailPassword.bind(this);
    this.state = {
      sign_up_details: {
        email: "",
        password: "",
        confirmpassword: "",
        notification: ""
      }
    };
  }
  
    createNewUserWithEmailPassword(event){
    event.preventDefault();
    if((this.state.sign_up_details.password !== "") && (this.state.sign_up_details.confirmpassword !== "")){
      if(this.state.sign_up_details.password === this.state.sign_up_details.confirmpassword){
        let updateNotification = Object.assign({}, this.state.sign_up_details, {notification: "Password matched"});
        this.setState({
          sign_up_details: updateNotification
        });

        app.auth().createUserWithEmailAndPassword(this.state.sign_up_details.email, this.state.sign_up_details.password)
        .catch(function(error) {
          // Handle Errors here.
          let errorCode = error.code;
          console.log(errorCode);
          let errorMessage = error.message;
          if (errorCode == 'auth/weak-password') {
            let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage});      
            this.setState({
              sign_up_details: notify
            });
          } else {
            // alert(errorMessage);
            let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage});      
            this.setState({
              sign_up_details: notify
            },
            () => {
              console.log(this.state.sign_up_details);
            } );
          }
          console.log(error);
        }).then(
          function(onResolve, onReject){
            console.log(onResolve);
            console.log(onReject);
          }
        );

      }else{
        let notify = Object.assign({}, this.state.sign_up_details, {notification: "Password not matched"});
        this.setState({
          sign_up_details: notify
        });
      }
    }
  }
  
    handleChangeforSignUp(event){
    // console.log(event);
    const  target = event.target;
    let emailInput = "";
    let passwordInput = "";
    let confirmpasswordInput = "";
      
    if(target.type === 'email'){
      emailInput = target.value;
      let updateEmail = Object.assign({}, this.state.sign_up_details, {email: emailInput});
      this.setState({
        sign_up_details: updateEmail
      });

    }

    if(target.type === 'password' && target.name === 'password'){
      passwordInput = target.value;
      let updatePassword = Object.assign({}, this.state.sign_up_details, {password: passwordInput});      
      this.setState({
        sign_up_details: updatePassword
      });
    }

    if(target.type === 'password' && target.name === 'confirmpassword'){
      confirmpasswordInput = target.value;
      let updateConfirmpassword = Object.assign({}, this.state.sign_up_details, {confirmpassword: confirmpasswordInput});
      this.setState({
        sign_up_details: updateConfirmpassword
      });
    }
  }
  
  render() {
    
    const { from } = this.props.location.state || { from: { pathname: '/' } }
    //  const { from } = this.props.history.location || { from: { pathname: '/' } }
    
    if (this.state.redirect === true) {
      return <Redirect to={from} />
    }

    return (
        <div id="register" class="container tab-pane fade animated fadeIn">
          <form onSubmit={this.createNewUserWithEmailPassword} className="formfield" ref={(form) => { this.signupForm = form }} method="post">
              <h1 className="text-center login-heading pt-2 pb-4"><i className="fa fa-pencil fa-lg mx-2" ></i> Register</h1>
              {/* <input value={this.state.sign_up_details.name} onChange={this.handleChangeforSignUp}  className="form-control input mb-2" name="name" type="text" placeholder="John Doe" />               */}
              <input value={this.state.sign_up_details.email} onChange={this.handleChangeforSignUp}  className="form-control input mb-2" name="email" type="email" placeholder="[email protected]" />
              <input value={this.state.sign_up_details.password} onChange={this.handleChangeforSignUp}  className="form-control input mb-2" name="password" type="password" placeholder="*******" />
              <input value={this.state.sign_up_details.confirmpassword} onChange={this.handleChangeforSignUp}  className="form-control input mb-2" name="confirmpassword" type="password" placeholder="*******" />              
              <p className="text_ter text_pink">{this.state.sign_up_details.notification !== "" ? this.state.sign_up_details.notification : ""}</p>
              <input type="submit" className="btn btn-primary btn-sm btn-block p-2 mt-4 mb-2" value="Log In"></input>
          </form>
        </div>

     
    )
  }
}

ReactDOM.render(<Login/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>

<div id="app"><div>

enter image description here

9
  • 1
    On which line are you facing this issue? Make sure your functions that are making use of this are bound to the class. Commented Apr 2, 2018 at 13:59
  • 1
    Once inside the catch, your this does not refer to the component class, so it does not have any state. You should declare it outside the async request, something like let self = this.state and then use it. Commented Apr 2, 2018 at 14:02
  • check this answer How to do setState inside callback Commented Apr 2, 2018 at 14:03
  • The console showing error on else { // alert(errorMessage); let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage}); this.setState({ sign_up_details: notify }, () => { console.log(this.state.sign_up_details); } ); in this block of code Commented Apr 2, 2018 at 14:15
  • 1
    @Ionut Thanks, trying Commented Apr 2, 2018 at 14:17

2 Answers 2

0

You seem to be using react-router (which gives you the Redirect component for example) but it's never imported or included anywhere?

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, But redirection is not the part of this error. Something is wrong in the this.state.signup_details. Its just a piece of code of a complete application. @timotgl
May I set the state of particular class in promises? @timotgl
@kropani Try changing the methods so that they have the component in scope with this.: createNewUserWithEmailPassword = (event) => {} Same for the other methods.
0

So this error is the equivalent to you having written undefined.state

Take a look at your event handlers such as handleChangeForSignup() which you are using bad practice in your naming, its not completely camel case, you have handleChangeforSignup().

Specifically relating to this error though, look at createNewUserWithEmailPassword().

Did you try testing it out first by doing:

createNewUserWithEmailPassword(event) {
    event.preventDefault();

    console.log(this.state.sign_up_details);
  }

Do you see another problem here? Again, naming convention. You need this event handler to do one thing at a time. You see how the console log I added would not work? It would only check for email, but if you would have done this first, you know take it one step at a time and test your code along the way, you probably would have gotten this error earlier.

JavaScript thinks that inside your createNewUserWithEmailPassword() is not equal to this, but instead this is equal to undefined.

You need to review what the this keyword is used for inside of a class and how the value of this is determined inside a function.

Your Login instance should have a few different properties such as state, render() and createNewUserWithEmailPassword().

You should be able to reference the keyword this which is a reference back to the class itself.

So you are saying give me the reference to the instance of Login that I am writing code inside of. That should give you access to state, render() and createNewUserWithEmailPassword().

I would clean up the code a bit like so:

class Login extends React.Component {
  state = {
      sign_up_details: {
        email: "",
        password: "",
        confirmpassword: "",
        notification: ""
      }
    };
  }

unless you are doing import React, { Component } from 'react'; but you did not include that in your post so I did React.Component.

So why is this is going wrong inside of createNewUserWithEmailPassword()?

To understand that, we need a good idea of how the value of this is determined inside a function.

class Car {
    setDriveSound(){
    this.sound = sound;
  }

  drive() {
    return this.sound;
  }
}

This is just a dummy class that allows us to set a value and later return that value.

class Car {
    setDriveSound(sound){
    this.sound = sound;
  }

  drive() {
    return this.sound;
  }
}

const car = new Car();
car.setDriveSound('vroom');
car.drive();

This will output vroom.

So here is an important rule to understand. Whenever we want to figure out what the value of this is going to be inside of a method on a class, don't look at the method itself, look at where you called the method.

In my example above, we look at car.drive();.

We find the function name, in this case drive(), we look to the dot to the left of the function, and look at the variable that is referenced inside.

So this from return this.sound; inside the drive() method is going to be equal to the car variable inside the Car class.

So, don't look at the function, look at where the function is called. What is to the left of dot when the function gets called.

So when drive() is called on car, this becomes equal to the instance of the car.

I will create an object called truck and rip off the drive() function from the instance of car and assign it to the truck object:

const truck = {
    sound: "honk_honk",
    driveMyTruck: car.drive
}

truck.driveMyTruck();

This will return honk_honk because truck is equal to this inside the drive() function.

The latter is the equivalent to doing:

drive() {
  return truck.sound;
}

Lets apply the above so what is going on in your case.

Now if I try this:

const drive = car.drive;

drive();

Now I would get Cannot read property 'sound' of undefined.

So when the callback is passed down the form element at some point in time we are going to call createNewUserWithEmailPassword() and when it gets invoked, there is no Login createNewUserWithEmailPassword.

This example here:

class Car {
    setDriveSound(sound){
    this.sound = sound;
  }

  drive() {
    return this.sound;
  }
}

const car = new Car();
car.setDriveSound('vroom');

const drive = car.drive;

drive();

is exactly what you did, or what you have going on.

This may still be confusing, it's not an easy concept to understand, I get this type of error message very frequently as well.

So how would you apply what I just explained?

There are several ways to solve your problem.

Now, you added a constructor(props) method with super(props) because it extends React.Component and you did this.createNewUserWithEmailPassword = this.createNewUserWithEmailPassword.bind(this);

This should have produced a new version of the function and it should have been fixed with the correct value of this, but it didn't solve it.

So try this:

class Login extends React.Component {
  state = {
      sign_up_details: {
        email: "",
        password: "",
        confirmpassword: "",
        notification: ""
      }
    };

    createNewUserWithEmailPassword = (event) => {
       event.preventDefault();

       console.log(this.state.sign_up_details);
    }
 }

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.