我正在尝试在我的注册表单上使用 ReactJS 创建客户端验证。我使用http://validatejs.org/库进行验证,并使用https://github.com/jhudson8/react-semantic-ui组件来渲染语义 ui React 组件。这是代码。
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>);
}
});
我遇到的问题是,当我调用 this.setState 时,状态不会立即更新,因此当我调用 validate(this.state.data,constraints) 时,我正在验证以前的状态,因此用户的 UI 体验变得很奇怪,例如:
如果我的电子邮件字段中有“example@em”并输入“a”,它将验证字符串“example@em”而不是“example@ema”,因此本质上它总是在新的击键之前验证状态。我一定在这里做错了什么。我知道组件的状态不会立即更新,只有在渲染完成后。
我应该在渲染函数中进行验证吗?
- - 解决方案 - -
像 Felix Kling 建议的那样向 setState 添加回调解决了它。这是带有解决方案的更新代码:
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>);
}
});
--- 更好的解决方案 -----
请参阅下面的 FakeRainBrigand 的解决方案。