2

I am new to reactjs. I have taken sample code from the react documentation (https://facebook.github.io/react/docs/forms.html) and modified it very slightly to create the following class:

class LoginView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {email: '',
                  password: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    alert(this.state.email);
    this.setState({email: event.target.email});
    this.setState({password: event.target.password});
  }

  handleSubmit(event) {
    alert(this.state.email);
    var response = fetch('http://0.0.0.0:5000/v1/authtoken/', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*'
        },
        body: JSON.stringify({
          email: this.state.email,
          password: this.state.password,
        })
      }).then((response) => response.json())
    var token = response.token
    alert([token])
    event.preventDefault();
  }

  render() {
    return (
      <div className="login-form">
        <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="email">Email address:</label>
            <input type="email" className="form-control" id="email" value={this.state.email} onChange={this.handleChange}/>
          </div>
          <div className="form-group">
            <label htmlFor="pwd">Password:</label>
            <input type="password" className="form-control" id="pwd" value={this.state.password} onChange={this.handleChange}/>
          </div>
          <div className="checkbox">
            <label><input type="checkbox"/> Remember me</label>
          </div>
          <button type="submit" className="btn btn-default">Submit</button>
        </form>
      </div>
    );
  }
}

export default LoginView

The purpose of the class is to present a login form which will post the value of the email and password fields to an endpoint. I am pulling my hair out over the way the this.state object is behaving.

Note that there is an alert in both handleSubmit and handlechange. These alerts should contain the value of the email field, but they instead contain the value undefined. What is confusing me is that the fields themselves, which also present values from this.state.email, actually work. This means that state is somehow being saved, but it just isn't available within the functions.

I've been pouring over this for hours and am at a loss as to how I could be getting this behavior. Any help would be very appreciated.

melchoir55
  • 6,842
  • 7
  • 60
  • 106
  • 1
    Not the problem you're reporting right now but you're attempting to access `response.token` before the asynchronous `fetch` completes in `handleSubmit` – Phil Jan 17 '17 at 02:39

1 Answers1

3

In handleChange(), event.target.email and event.target.password is not valid.

event is the onChange event for the particular field that is changing. event.target returns the DOMEventTarget (https://facebook.github.io/react/docs/events.html) which is a reference to the object that dispatched the event.

So in your case, event.target is the input field that triggered the onChange.

You will need to update this to:

// If you use ES6 you can do this to use `event.target.type` as a key
handleChange(event) {
  this.setState({
    [event.target.type]: event.target.value
  });
}
// Otherwise, you can do it like this
handleChange(event) {
  var newState = {};
  newState[event.target.type] = event.target.value;
  this.setState(newState);
}

event.target.type will return the <input> type which for your case is either 'email' or 'password'. and event.target.value will return the value which you want to update.

Additional note: Calling .setState(nextState) will perform a shallow merge of nextState into current state. So you do not need to update both email and password in your handleChange function. https://facebook.github.io/react/docs/react-component.html#setstate

Calvin
  • 1,305
  • 8
  • 17
  • I tried replacing handleChange with your recommendation, but it did not seem to help. The syntax you've suggested is confusing me, though it might just be my unfamiliarity with react. Doesn't your syntax create a key/value pair where the key is an array with a single element? I don't understand how that would modify either this.state.email or this.state.password? Also, I'm not sure what you mean by saying `same thing goes for handleSubmit`. I don't call event in `handleSubmit`. – melchoir55 Jan 17 '17 at 03:11
  • The syntax is useable if you use ES6. I've edited the answer to give the alternative method – Calvin Jan 17 '17 at 03:19
  • Added additional info regarding how setState() works. – Calvin Jan 17 '17 at 03:23