2015-10-01 13 views
7

Tôi đang cố gắng làm điều gì đó trong React sẽ rất đơn giản trong bất kỳ khung công tác nào khác: Tôi muốn thu thập một loạt các giá trị từ một biểu mẫu.Thực hành tốt nhất để đọc dữ liệu biểu mẫu trong React

Trước đây tôi đã làm việc này với một Backbone View, và nó rất đơn giản:

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

Nhưng trong Phản ứng tôi dường như không thể tìm thấy một cách dễ dàng để làm điều đó. Có vẻ như lựa chọn duy nhất của tôi là để ...

LƯU Ý: Xin lỗi cho các định dạng: khối mã và danh sách không chơi tốt với nhau :-(

  1. hoàn toàn bỏ qua phản ứng và sử dụng jQuery + e.target để truy cập các hình thức:

    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>;

    }

    đó làm việc, và là đơn giản, nhưng nó cảm thấy như mình đang bỏ qua phản ứng và sử dụng JQuery khi tôi nên chỉ sử dụng React.

  2. Cung cấp callbacks để mỗi điều khiển biểu mẫu:

    handleFooClick: function(e) {

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

    },

    render: function() {

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

    }

    Đây dường như là cách phản ứng/thông lượng, nhưng nó cảm thấy như một lượng công việc không cần thiết. Trong ví dụ Backbone của tôi, tôi chỉ cần một dòng cho mỗi điều khiển biểu mẫu, nhưng với cách tiếp cận này, mọi điều khiển cuối cùng mà tôi xây dựng phải có trình xử lý onChange của riêng nó (và tôi phải móc trình xử lý đó cho mọi phần tử khi tôi render nó).

    EDIT: Thêm một bất lợi của phương pháp này là bên trong callbacks this.propsthis.state sẽ không trỏ đến điều khiển biểu mẫu của tôi props/tiểu bang (nó sẽ trỏ đến đầu vào của props/tiểu bang). Điều này có nghĩa rằng không chỉ tôi phải viết một trình xử lý cho mỗi đầu vào VÀ thêm gọi lại đó vào mọi đầu vào khi tôi render, nhưng tôi cũng phải chuyển đối tượng dữ liệu của mình tới mọi đầu vào!

  3. Sử dụng refs:

    handleSubmit: function(e) {

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

    },

    render: function() {

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

    }

    Điều này có vẻ như một giải pháp lành mạnh hơn, vì tôi chỉ cần thêm thuộc tính "ref" vào mọi điều khiển biểu mẫu và sau đó tôi có thể đọc dữ liệu dễ dàng như trong Backbone. Tuy nhiên, tất cả các tài liệu React cho thấy rằng việc sử dụng refs theo cách đó là sai (tất cả các ví dụ sử dụng refs liên quan đến việc gửi tín hiệu đến các điều khiển, ví dụ như "tập trung vào đầu vào này", chứ không phải đọc dữ liệu ra khỏi các điều khiển).

Tôi cảm thấy phải có cách "Phản ứng" để truy cập dữ liệu biểu mẫu không cần thiết phức tạp, nhưng tôi không thấy nó vì tôi không hiểu đủ. Nếu bất kỳ chuyên gia React nào có thể giải thích những gì tôi đang bỏ lỡ, tôi sẽ đánh giá cao nó.

Trả lời

2

Thứ nhất, jQuery là một sự phụ thuộc không cần thiết và nó không phải là lựa chọn sạch nhất vì vậy hãy loại trừ nó ra.

Tiếp theo, ref có vấn đề về tính linh hoạt. Xem chi tiết answer để biết chi tiết. Hãy quy tắc refs ra cho tất cả, nhưng các trường hợp đơn giản nhất.

Tùy chọn # 2 - những gì Facebook gọi controlled components. Các thành phần được kiểm soát là rất tốt vì chúng bao gồm tất cả các trường hợp sử dụng (như xác thực trên khóa). Mặc dù không có nhiều mã, nếu bạn không muốn thêm một trình xử lý thay đổi đơn giản cho từng phần tử biểu mẫu, bạn có thể sử dụng một trình xử lý thay đổi cho tất cả các phần tử với việc sử dụng bind. Một cái gì đó như thế này:

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

Hoặc để biết cách làm sạch hơn, hãy xem điều này answer.

1

Bạn có thể sử dụng ReactLink để tạo liên kết hai chiều giữa thành phần phản ứng và trạng thái của bạn.

mô tả ở đây: https://facebook.github.io/react/docs/two-way-binding-helpers.html

+0

Đó là một gợi ý tuyệt vời; Tôi thậm chí còn không biết rằng 'ReactLink' tồn tại. Tuy nhiên, tôi thấy hai điều liên quan đến nó. Đầu tiên, bài viết bạn đã liên kết bắt đầu với "Nếu bạn mới làm quen với khung công tác, hãy lưu ý rằng ReactLink không cần thiết cho hầu hết các ứng dụng và nên được sử dụng thận trọng." Thứ hai, nó xuất hiện để yêu cầu một hỗn hợp, và tôi nghĩ rằng mix-in đã không được chấp nhận trong React? – machineghost

1

Đối với một dự án nhỏ tôi đã được sử dụng một cuộc gọi onChange đơn lại cho tất cả các đầu vào - một cái gì đó như thế này ...

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

này yêu cầu bạn đặt tên cho nguyên liệu đầu vào của bạn giống như bạn đặt tên cho tài sản nhà nước của họ, nhưng Tôi khá thích điều đó. Sau đó, bạn cung cấp giá trị được lưu trữ trong trạng thái cho thuộc tính giá trị của đầu vào của bạn và bạn đã sẵn sàng - tất cả trạng thái biểu mẫu của bạn được lưu trữ ở một nơi với một hàm xử lý duy nhất.

Tất nhiên có nhiều cách mở rộng hơn - tôi chỉ đọc về một khuôn khổ cho phản ứng được gọi là formsy trông thú vị.Dưới đây là một hướng dẫn: http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html

Hy vọng rằng sẽ giúp

Dan

1

Đây là cách tôi xử lý tất cả các lĩnh vực trong một hình thức.

  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

Bạn có thể đọc dữ liệu biểu mẫu chỉ bằng một hàm.

lớp hinh kéo dài 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; 
Các vấn đề liên quan