I am trying to create client side validation with ReactJS on my registration form. I am using http://validatejs.org/ library for validations along with https://github.com/jhudson8/react-semantic-ui components for rendering semantic-ui React components. Here is the code.
var constraints = {
  email: {
    presence: true, 
    email:true
  }, 
  password: {
    presence: true,
    length: { minimum: 5 }
  }
}
var RegistrationForm = React.createClass({
  getInitialState: function() {
    return { 
      data: {},
      errors: {}
    };
  },
  changeState: function () {
    this.setState({
      data: {
        email: this.refs.email.getDOMNode().value,
        password: this.refs.password.getDOMNode().value,
        password_confirmation:  this.refs.password_confirmation.getDOMNode().value
      }
    });
    console.log("State after update");
    console.log(this.state.data);
  },
  handleChange: function(e) {
    this.changeState();
    var validation_errors = validate(this.state.data, constraints);
    if(validation_errors){
      console.log(validation_errors);
      this.setState({errors: validation_errors});
    }
    else
      this.setState({errors: {}});
  },
  handleSubmit: function(e) {
    e.preventDefault();
    //code left out..
  },
  render: function() {
    var Control = rsui.form.Control;
    var Form = rsui.form.Form;
    var Text = rsui.input.Text;
    var Button = rsui.form.Button;
    return (
      <Form onSubmit={this.handleSubmit} onChange={this.handleChange}>
        <h4 className="ui dividing header">New User Registration</h4>
        <Control label="Email" error={this.state.errors.email}>
          <Text name="email" type="email" ref="email"  key="email" value={this.state.data.email}></Text>
        </Control>
        <Control label="Password" error={this.state.errors.password}>
          <Text name="password" type="password" ref="password" key="password" value={this.state.data.password}></Text>
        </Control>
        <Control label="Password Confirmation">
          <Text name="password_confirmation" type="password" ref="password_confirmation" key="password_confirmation" value={this.state.data.password_confirmation}></Text>
        </Control>
        <Button> Register </Button>
      </Form>);
  }
});
The problem I am having is that when I call this.setState, the state is not immediately updated, so when I call validate(this.state.data, constraints) I am validating previous state, so user's UI experience gets weird, for example:
If I have 'example@em' in my email field and I enter 'a', it will validate string 'example@em' not 'example@ema', so in essence it always validates the state before the new key stroke. I must be doing something fundamentally wrong here. I know state of the component is not updated right away, only after render is done.
Should I be doing validations in render function ?
--- SOLUTION ---
Adding a callback to setState like Felix Kling suggested solved it. Here is the updated code with solution:
var RegistrationForm = React.createClass({
  getInitialState: function() {
    return { 
      data: {},
      errors: {}
    };
  },
  changeState: function () {
    this.setState({
      data: {
        email: this.refs.email.getDOMNode().value,
        password: this.refs.password.getDOMNode().value,
        password_confirmation: this.refs.password_confirmation.getDOMNode().value
      }
    },this.validate);
  },
  validate: function () {
    console.log(this.state.data);
    var validation_errors = validate(this.state.data, constraints);
    if(validation_errors){
      console.log(validation_errors);
      this.setState({errors: validation_errors});
    }
    else
      this.setState({errors: {}});
  },
  handleChange: function(e) {
    console.log('handle change fired');
    this.changeState();
  },
  handleSubmit: function(e) {
    e.preventDefault();
    console.log(this.state);
  },
  render: function() {
    var Control = rsui.form.Control;
    var Form = rsui.form.Form;
    var Text = rsui.input.Text;
    var Button = rsui.form.Button;
    return (
      <Form onSubmit={this.handleSubmit} onChange={this.handleChange}>
        <h4 className="ui dividing header">New Rowing Club Registration</h4>
        <Control label="Email" error={this.state.errors.email}>
          <Text name="email" type="email" ref="email"  key="email" value={this.state.data.email}></Text>
        </Control>
        <Control label="Password" error={this.state.errors.password}>
          <Text name="password" type="password" ref="password" key="password" value={this.state.data.password}></Text>
        </Control>
        <Control label="Password Confirmation">
          <Text name="password_confirmation" type="password" ref="password_confirmation" key="password_confirmation" value={this.state.data.password_confirmation}></Text>
        </Control>
        <Button> Register </Button>
      </Form>);
  }
});
--- BETTER SOLUTION -----
See FakeRainBrigand's solution below.