如何使用React.JS正确validationinput值?

我有一个简单的表单。 所有的组件和状态都保存在Page组件中。 有2个显示标题和3个input字段。 第一个input应该是文本,第二个和第三个应该是整数。 当用户input错误types的数据时,我想在input字段旁边popup错误消息。 我的问题涉及到React.JS的最佳实践

谁决定价值是有效的? 我猜想input域的唯一工作就是将值返回到保存状态的组件,那么这是否意味着只有Page可以确定某个值是否有效?

那我应该怎么popup来呢? 页面是否必须触发一个新的布尔状态元素,它将通过perp传递给Adaptive_Input来显示错误信息?

的jsfiddle

JS:

/** * @jsx React.DOM */ var Adaptive_Input = React.createClass({ handle_change: function(){ var new_text = this.refs.input.getDOMNode().value; this.props.on_Input_Change(new_text); }, render: function(){ return ( <div className='adaptive_placeholder_input_container'> <input className="adaptive_input" type="text" required="required" onChange= {this.handle_change} ref="input" ></input> <label className="adaptive_placeholder" alt={this.props.initial} placeholder={this.props.focused} ></label> </div> ); } }); var Form = React.createClass({ render: function(){ return ( <form> <Adaptive_Input initial={'Name Input'} focused={'Name Input'} on_Input_Change={this.props.handle_text_input} /> <Adaptive_Input initial={'Value 1'} focused={'Value 1'} on_Input_Change={this.props.handle_value_1_input} /> <Adaptive_Input initial={'Value 2'} focused={'Value 2'} on_Input_Change={this.props.handle_value_2_input} /> </form> ); } }); var Page = React.createClass({ getInitialState: function(){ return { Name : "No Name", Value_1 : '0', Value_2 : '0', Display_Value: '0' }; }, handle_text_input: function(new_text){ this.setState({ Name: new_text }); }, handle_value_1_input: function(new_value){ console.log("==="); var updated_display = parseInt(new_value) + parseInt(this.state.Value_2); updated_display = updated_display.toString(); this.setState({ Display_Value: updated_display }); }, handle_value_2_input: function(new_value){ var updated_display = parseInt(this.state.Value_1) + parseInt(new_value); updated_display = updated_display.toString(); this.setState({ Display_Value: updated_display }); }, render: function(){ return( <div> <h2>{this.state.Name}</h2> <h2>Value 1 + Value 2 = {this.state.Display_Value}</h2> <Form handle_text_input={this.handle_text_input} handle_value_1_input = {this.handle_value_1_input} handle_value_2_input = {this.handle_value_2_input} /> </div> ); } }); React.renderComponent(<Page />, document.body); 

首先,下面是我将要提到的一个例子: http : //jsbin.com/rixido/2/edit

如何使用React.JS正确validationinput值?

随你怎么便。 React用于呈现数据模型。 数据模型应该知道什么是有效的。 您可以使用Backbone模型,JSON数据或任何您想要表示数据的错误状态。

进一步来说:

反应对你的数据通常是不可知的。 这是为了渲染和处理事件。

遵循的规则是:

  1. 元素可以改变他们的状态。
  2. 他们不能改变道具。
  3. 他们可以调用callback来改变顶级道具。

如何决定是否应该成为道具或国家? 考虑一下:除了文本字段,你的应用程序的任何部分是否想要知道input的值是不好的? 如果不是,就把它变成一个状态。 如果是的话,它应该是一个道具。

例如,如果您想要单独的视图来渲染“您在此页面上有两个错误”。 那么你的错误将不得不被知道的顶级数据模型。

那个错误在哪里?
如果您的应用程序正在渲染Backbone模型(例如),则模型本身将具有可以使用的validate()方法和validateError属性。 您可以渲染其他可以执行相同操作的智能对象。 React还表示,尽量将道具保持在最低限度,并生成其余的数据。 所以如果你有一个validation器(例如https://github.com/flatiron/revalidator ),那么你的validation可能会下降,任何组件可以检查与匹配validation的道具,看看它是否有效。

这主要取决于你。

(我个人使用的骨干模型和渲染他们在React中。我有一个顶层错误警报,显示是否有任何错误,描述错误。

你可以使用npm install --save redux-form

我写一个简单的电子邮件和提交button的forms,这将validation电子邮件和提交表单。 使用redux-form,默认情况下在html onSubmit action上运行event.preventDefault()。

 import React, {Component} from 'react'; import {reduxForm} from 'redux-form'; class LoginForm extends Component { onSubmit(props) { //do your submit stuff } render() { const {fields: {email}, handleSubmit} = this.props; return ( <form onSubmit={handleSubmit(this.onSubmit.bind(this))}> <input type="text" placeholder="Email" className={`form-control ${email.touched && email.invalid ? 'has-error' : '' }`} {...email} /> <span className="text-help"> {email.touched ? email.error : ''} </span> <input type="submit"/> </form> ); } } function validation(values) { const errors = {}; const emailPattern = /(.+)@(.+){2,}\.(.+){2,}/; if (!emailPattern.test(values.email)) { errors.email = 'Enter a valid email'; } return errors; } LoginForm = reduxForm({ form: 'LoginForm', fields: ['email'], validate: validation }, null, null)(LoginForm); export default LoginForm; 

我已经写了这个库 ,它允许你包装你的表单元素组件,并让你定义你的validation器的格式为: –

 <Validation group="myGroup1" validators={[ { validator: (val) => !validator.isEmpty(val), errorMessage: "Cannot be left empty" },... }]}> <TextField value={this.state.value} className={styles.inputStyles} onChange={ (evt)=>{ console.log("you have typed: ", evt.target.value); } }/> </Validation> 

你的jsfiddle不起作用了。 我已经修复它: http : //jsfiddle.net/tkrotoff/bgC6E/28/使用React 15.5和ES6类。

 class Adaptive_Input extends React.Component { handle_change(e) { var new_text = e.currentTarget.value; this.props.on_Input_Change(new_text); } render() { return ( <div className="adaptive_placeholder_input_container"> <input className="adaptive_input" type="text" required="required" onChange={this.handle_change.bind(this)} /> <label className="adaptive_placeholder" alt={this.props.initial} placeholder={this.props.focused} /> </div> ); } } class Form extends React.Component { render() { return ( <form> <Adaptive_Input initial={'Name Input'} focused={'Name Input'} on_Input_Change={this.props.handle_text_input} /> <Adaptive_Input initial={'Value 1'} focused={'Value 1'} on_Input_Change={this.props.handle_value_1_input} /> <Adaptive_Input initial={'Value 2'} focused={'Value 2'} on_Input_Change={this.props.handle_value_2_input} /> </form> ); } } class Page extends React.Component { constructor(props) { super(props); this.state = { Name: 'No Name', Value_1: '0', Value_2: '0', Display_Value: '0' }; } handle_text_input(new_text) { this.setState({ Name: new_text }); } handle_value_1_input(new_value) { new_value = parseInt(new_value); var updated_display = new_value + parseInt(this.state.Value_2); updated_display = updated_display.toString(); this.setState({ Value_1: new_value, Display_Value: updated_display }); } handle_value_2_input(new_value) { new_value = parseInt(new_value); var updated_display = parseInt(this.state.Value_1) + new_value; updated_display = updated_display.toString(); this.setState({ Value_2: new_value, Display_Value: updated_display }); } render() { return( <div> <h2>{this.state.Name}</h2> <h2>Value 1 + Value 2 = {this.state.Display_Value}</h2> <Form handle_text_input={this.handle_text_input.bind(this)} handle_value_1_input={this.handle_value_1_input.bind(this)} handle_value_2_input={this.handle_value_2_input.bind(this)} /> </div> ); } } ReactDOM.render(<Page />, document.getElementById('app')); 

现在,与表单validation相同的代码感谢这个库: https : //github.com/tkrotoff/react-form-with-constraints => http://jsfiddle.net/tkrotoff/k4qa4heg/

http://jsfiddle.net/tkrotoff/k4qa4heg/

 const { FormWithConstraints, FieldFeedbacks, FieldFeedback } = ReactFormWithConstraints; class Adaptive_Input extends React.Component { static contextTypes = { form: PropTypes.object.isRequired }; handle_change(e) { var new_text = e.currentTarget.value; this.props.on_Input_Change(e, new_text); } className(name) { let className = 'adaptive_placeholder_input_container'; const form = this.context.form; if (form.fieldsStore.containErrors(name)) { className += ' error'; } else if (form.fieldsStore.containWarnings(name)) { className += ' warning'; } return className; } render() { return ( <div className={this.className(this.props.name)}> <input type={this.props.type} name={this.props.name} className="adaptive_input" required onChange={this.handle_change.bind(this)} /> <label className="adaptive_placeholder" alt={this.props.initial} placeholder={this.props.focused} /> </div> ); } } class Form extends FormWithConstraints { constructor(props) { super(props); this.state = { Name: 'No Name', Value_1: '0', Value_2: '0', Display_Value: '0' }; } handle_text_input(e, new_text) { this.form.validateFields(e.currentTarget); this.setState({ Name: new_text }); } handle_value_1_input(e, new_value) { this.form.validateFields(e.currentTarget); if (this.form.isValid()) { new_value = parseInt(new_value); var updated_display = new_value + parseInt(this.state.Value_2); updated_display = updated_display.toString(); this.setState({ Value_1: new_value, Display_Value: updated_display }); } else { this.setState({ Display_Value: 'Error' }); } } handle_value_2_input(e, new_value) { this.form.validateFields(e.currentTarget); if (this.form.isValid()) { new_value = parseInt(new_value); var updated_display = parseInt(this.state.Value_1) + new_value; updated_display = updated_display.toString(); this.setState({ Value_2: new_value, Display_Value: updated_display }); } else { this.setState({ Display_Value: 'Error' }); } } render() { return( <div> <h2>Name: {this.state.Name}</h2> <h2>Value 1 + Value 2 = {this.state.Display_Value}</h2> <FormWithConstraints ref={form => this.form = form} noValidate> <Adaptive_Input type="text" name="name_input" initial={'Name Input'} focused={'Name Input'} on_Input_Change={this.handle_text_input.bind(this)} /> <FieldFeedbacks for="name_input"> <FieldFeedback when="*" error /> <FieldFeedback when={value => !/^\w+$/.test(value)} warning>Should only contain alphanumeric characters</FieldFeedback> </FieldFeedbacks> <Adaptive_Input type="number" name="value_1_input" initial={'Value 1'} focused={'Value 1'} on_Input_Change={this.handle_value_1_input.bind(this)} /> <FieldFeedbacks for="value_1_input"> <FieldFeedback when="*" /> </FieldFeedbacks> <Adaptive_Input type="number" name="value_2_input" initial={'Value 2'} focused={'Value 2'} on_Input_Change={this.handle_value_2_input.bind(this)} /> <FieldFeedbacks for="value_2_input"> <FieldFeedback when="*" /> </FieldFeedbacks> </FormWithConstraints> </div> ); } } ReactDOM.render(<Form />, document.getElementById('app')); 

在这里提出的解决scheme是hackish,因为我试图保持它接近原来的jsfiddle。 为了使用react-form-with-constraints进行正确的表单validation,请查看https://github.com/tkrotoff/react-form-with-constraints#examples