在React中读取表单数据的最佳实践

时间:2015-10-01 00:12:55

标签: reactjs

我正在尝试在React中做一些在任何其他框架中都非常简单的事情:我想从表单中收集一堆值。

以前我用Backbone View做过这种事情,这很简单:

readFormValues: function() {
    this.data.foo = this.$('[name="foo"]').val();
    this.data.bar = this.$('[name="bar"]:checked').val();
});

但在React中我似乎无法找到一种简单的方法。看来我唯一的选择就是......

注意:格式化的道歉:代码块和列表不能很好地协同工作: - (

  1. 完全绕过React并使用jQuery + e.target访问表单:

    handleSubmit: function(e) {

    var $form = $(e.target).parents('form:first');

    this.data.foo = $form.find('[name="foo"]);

    },

    render: function() {

    return <form onSubmit="handleSubmit"><input name="foo"/></form>;

    }

    这很有效,而且很简单,但感觉就像我在使用React时绕过React并使用JQuery。

  2. 为每个表单控件提供回调:

    handleFooClick: function(e) {

    this.data.foo = event.target.value;

    },

    render: function() {

    return <form><input name="foo" onChange="handleFooChange"/></form>;

    }

    这似乎是React / Flux的方式,但感觉就像一堆疯狂的不必要的工作。在我的Backbone示例中,每个表单控件只需要一行,但是使用这种方法我构建的每个最后一个控件都必须有自己的onChange处理程序(我必须在处理它时将该处理程序挂钩到每个元素)。

    编辑:此方法的另一个缺点是回调内部this.propsthis.state不会指向我的表单控件的props / state(它将指向输入的道具/州)。这意味着我不仅需要为每个输入编写一个处理程序,并在渲染时将该回调添加到每个输入,但我还必须将我的数据对象传递给每个输入!

  3. 使用refs:

    handleSubmit: function(e) {

    this.state.data.foo = this.refs.foo.value;

    },

    render: function() {

    return <form><input ref="foo"/></form>;

    }

    这似乎是一个更理智的解决方案,因为我只需要为每个表单控件添加一个“ref”属性,然后我就可以像在Backbone中一样轻松地读取数据。但是,所有的React文档都表明使用refs的方法是错误的(所有使用refs的例子都涉及向控件发送信号,例如“专注于此输入”,而不是从控件中读取数据)。

  4. 我觉得必须有一种“React-ive”方式来访问我的表格数据,这种表格数据并非不必要的复杂,但我没有看到它,因为我不太了解React。如果任何React专家能够解释我所缺少的东西,我将非常感激。

6 个答案:

答案 0 :(得分:3)

首先,jQuery是一种不必要的依赖,它不是最干净的选择,所以让我们排除它。

接下来,裁判有灵活性问题。有关详细信息,请参阅此answer。除了最简单的情况之外,让我们的规则适用于所有情况。

留下选项#2 - Facebook称之为controlled components。受控组件很棒,因为它们涵盖了所有用例(例如keyup上的验证)。虽然代码不多,但如果您不想为每个表单元素添加简单的更改处理程序,则可以使用bind为所有元素使用一个更改处理程序。像这样:

handleChange: function(fieldName, e) {
  console.log("field name", fieldName);
  console.log("field value", e.target.value);
  // Set state or use external state.
},

render: function() {
  var someValue = this.state.someValue; // Or a prop is using external state
  return (
    <div>
      <input 
        name="someName" 
        value={someValue} 
        onChange={this.handleChange.bind(this, "someName")} />
    </div>
  )
}

或者更清洁的方式,请参阅此answer

答案 1 :(得分:1)

您可以使用ReactLink在反应组件和州之间创建双向绑定。

此处描述:https://facebook.github.io/react/docs/two-way-binding-helpers.html

答案 2 :(得分:1)

对于一个较小的项目,我一直在使用单个onChange回调所有输入 - 就像这样......

HandleClick(event) {
    let values = this.state.values;
    values[event.target.name] = event.target.value;
    this.setState({values});
}

这要求您为输入命名与命名状态属性相同,但我非常喜欢。然后,将状态存储的值提供给输入的value属性,然后全部设置 - 所有表单状态都存储在一个具有单个处理函数的位置。

当然还有更多可扩展的方式 - 我只是在阅读一个看起来很有趣的反应框架。这是一个教程: http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html

希望有所帮助

答案 3 :(得分:1)

这是我处理表单中所有字段的方式。

            var My_Field=React.createClass({
                _onChange: function(evt) {
                    var e=this.props.parent_form;
                    if (e) {
                        e.setState({email: evt.target.value});
                    }
                },
                render: function() {
                    return (
                        <input type="text" name={this.props.name} placeholder={this.props.label} onChange={this._onChange}/>
                    );
                }
            });

            var My_Form=React.createClass({
                getInitialState: function() {
                    return {
                        email: "",
                    };
                },
                _onSubmit: function(evt) {
                    evt.preventDefault();
                    alert(this.state.email);
                },
                render: function() {
                    return (
                        <form onSubmit={this._onSubmit}>
                            <My_Field name="email" label="Email" parent_form={this}/>
                            <input type="submit" value="Submit"/>
                        </form>
                    );
                }
            });

答案 4 :(得分:0)

您只需使用一个功能即可阅读表单数据。

类SignUp扩展了Component {

constructor(){
    super();
    this.handleLogin = this.handleLogin.bind(this);
}

handleLogin(e){
    e.preventDefault();
    const formData = {};
    for(const field in this.refs){
        formData[field] = this.refs[field].value;
    }
    console.log('-->', formData);
}
render(){
    return (
         <form onSubmit={this.handleLogin} className="form-horizontal">
                    <div className="form-group text-left">
                            <label className="control-label col-sm-2">Name:</label>
                            <div className="col-sm-10">
                            <input ref="name" type="text" className="form-control" name="name" placeholder="Enter name" />
                            </div>
                        </div>
                        <div className="form-group text-left">
                            <label className="control-label col-sm-2">Email:</label>
                            <div className="col-sm-10">
                            <input ref="email" type="email" className="form-control" name="email" placeholder="Enter email" />
                            </div>
                        </div>
                        <div className="form-group text-left">
                            <label className="control-label col-sm-2">Password:</label>
                            <div className="col-sm-10"> 
                            <input ref="password" type="password" className="form-control" name="password" placeholder="Enter password" />
                            </div>
                        </div>
                        <div className="form-group text-left"> 
                            <div className="col-sm-offset-2 col-sm-10">
                            <button type="submit" className="btn btn-primary btn-block">Signup</button>
                            </div>
                        </div>
                        </form>
 )        
} }export default SignUp;

答案 5 :(得分:0)

使用React的{​​{1}}:最快,最简单的方法:

useState()
相关问题