2015-10-01 31 views
7

我想在React中做一些在任何其他框架中都很簡單的操作:我想從表單中收集一堆值。在React中讀取表單數據的最佳實踐

以前我做這樣的事情有一個骨幹視圖,這是非常簡單的:

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

但在作出反應,我似乎無法找到一個簡單的方法來做到這一點。看來我唯一的選擇是......

注:道歉格式:代碼塊,並列出不在一起玩好:-(

  1. 完全繞過反應,並使用了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>;

    }

    這樣的作品,並且是簡單的,但感覺就像我繞過反應,使用JQuery時,我應該只正在使用React。

  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內不會指向我的表單控件的道具/狀態(這將指向輸入的道具/狀態)。這意味着我不僅必須爲每個輸入編寫一個處理程序,並且在我渲染時將該回調添加到每個輸入中,而且還必須將我的數據對象傳遞給每個輸入!

  3. 使用裁判:

    handleSubmit: function(e) {

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

    },

    render: function() {

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

    }

    這似乎是一個更加健全的解決方案,因爲我只需要爲每個表單控件添加一個「ref」屬性,然後我可以像在Backbone中一樣輕鬆讀取數據。但是,所有React文檔都建議使用refs這種方法是錯誤的(所有使用refs的例子都涉及向控件發送信號,例如「關注此輸入」,而不是讀取控件中的數據)。

我覺得必須有一個「響應,香港專業教育學院」的方式來訪問我的表單數據,是不是不必要的複雜性,但我沒有看到它,因爲我不明白作出反應不夠好。如果有任何React專家可以解釋我錯過了什麼,我將不勝感激。

回答

2

首先,jQuery是一個不必要的依賴,這不是最乾淨的選項,以便讓我們排除這種可能性。

接下來,參考文獻有靈活性的問題。有關詳細信息,請參見此answer。除了最簡單的情況之外,讓我們來裁決。

留下選項#2 - Facebook稱之爲controlled components。受控組件非常棒,因爲它們涵蓋了所有用例(如關鍵驗證)。雖然代碼不是很多,但如果您不想爲每個表單元素添加簡單的更改處理程序,則可以使用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

您可以使用ReactLink在您的反應組件和您的狀態之間創建一個雙向綁定。

說明如下:https://facebook.github.io/react/docs/two-way-binding-helpers.html

+0

這是一個偉大的建議;我甚至不知道有'ReactLink'存在。但是,我看到兩件有關它的事情。首先,您鏈接的文章首先是「如果您剛接觸框架,請注意ReactLink對於大多數應用程序不是必需的,應謹慎使用。」其次,它似乎需要混搭,我認爲在React中不贊成使用混合插件? – machineghost

1

因爲我一直在使用一個單一的onChange回調對所有輸入一個較小的項目 - 這樣的事情...

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

這要求你的名字你輸入一樣的,你說出自己國家的財產,但我很喜歡那樣。然後,將存儲在狀態中的值賦予輸入的value屬性,並且全部設置 - 所有表單狀態都通過一個處理函數存儲在一個位置。

當然還有更多可擴展的方式 - 我剛剛閱讀了一個叫做formsy的框架,看起來很有趣。這裏有一個教程: http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html

希望幫助

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> 
        ); 
       } 
      }); 
0

您只能使用一個函數讀取表單數據。

類註冊擴展組件{

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;