0

I am trying to learn how to work for Forms, State and Props. I created this form:

 render() {
        return (
            <div>
                <div className="container">
                    <form className="form-signin" onSubmit={this.loginClick.bind(this)}>
                        <control-label for="inputEmail" className="sr-only">Email address</control-label>
                        <input type="email" ref="username" id="inputEmail" className="form-control" placeholder="Email address" required autoFocus />
                        <control-label for="inputPassword" className="sr-only">Password</control-label>
                        <input type="password" ref="password" id="inputPassword" className="form-control" placeholder="Password" required />
                        <button className="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
                         </form>
                </div>
            </div>
        );
    }

And the submit method:

 loginClick(event) {
        event.preventDefault();
        let un = this.refs.username.value;
        let pw = this.refs.password.value
        this.setState(
            {
                username: un,
                password: pw
            }
        );
        console.log(this.state);
    }

However, what I find is that the first click, the log returns empty username and password. When I click the button the 2nd time, the username and password are correct. If I then modify the username or password, and click submit, no change. shows the old values. If I click a 2nd time, the values update.

What am I doing wrong? (Whole file here: https://github.com/CraigInBrisbane/ReactLearning/blob/master/components/signinbox.jsx)

Craig
  • 18,074
  • 38
  • 147
  • 248

1 Answers1

1

setState actions are asynchronous and are batched for performance gains. This is explained in documentation of setState:

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

So in your example, the state has not yet been updated. You can use a callback to check on the state when it has been updated:

loginClick(event) {
    event.preventDefault();
    let un = this.refs.username.value;
    let pw = this.refs.password.value
    this.setState({
            username: un,
            password: pw
        }, () => console.log(this.state)
    );
}

but that's not necessarily useful in your case. You can simply print out the value

loginClick(event) {
    event.preventDefault();
    let un = this.refs.username.value;
    let pw = this.refs.password.value
    this.setState({
            username: un,
            password: pw
    });
    console.log({
            username: un,
            password: pw
    });
}
klugjo
  • 19,422
  • 8
  • 57
  • 75
  • Ah thanks. So the 'log' was happening too early, basically? This is just learning code, and I was trying to validate that state had been updated. – Craig Dec 11 '17 at 10:13
  • more like `this.setState` is asynchronous. Just like an AJAX call, so if you call `this.state` directly after, it won't be updated yet – klugjo Dec 11 '17 at 10:14