2015-01-09 24 views
110

Tôi có cấu trúc sau:Cách truy cập trạng thái của trẻ trong React?

FormEditor - giữ nhiều FieldEditor FieldEditor - chỉnh sửa một lĩnh vực hình thức và tiết kiệm giá trị khác nhau về nó ở đó là nhà nước

Khi một nút được nhấp trong vòng FormEditor, tôi muốn có thể thu thập thông tin về các trường từ tất cả các thành phần FieldEditor, thông tin ở trạng thái của chúng và có tất cả trong FormEditor.

Tôi đã xem xét lưu trữ thông tin về các trường bên ngoài trạng thái của FieldEditor và đặt trạng thái đó ở trạng thái FormEditor. Tuy nhiên, điều đó sẽ yêu cầu FormEditor để nghe từng thành phần của nó là FieldEditor khi chúng thay đổi và lưu trữ thông tin của chúng trong trạng thái của nó.

Tôi không thể chỉ truy cập trạng thái của trẻ em? Nó có lý tưởng không?

+4

* "Tôi không thể truy cập trạng thái của trẻ em được không? Nó có lý tưởng không?" * Không. Nhà nước là thứ gì đó bên trong và không bị rò rỉ ra bên ngoài. Bạn có thể thực hiện các phương thức accessor cho thành phần của bạn, nhưng thậm chí đó không phải là lý tưởng. –

+0

@FelixKling Sau đó, bạn đang gợi ý rằng cách lý tưởng để giao tiếp với cha mẹ là sự kiện duy nhất? –

+3

Có, sự kiện là một cách. Hoặc có một luồng dữ liệu một hướng như Flux khuyến khích: https://facebook.github.io/flux/ –

Trả lời

69

Nếu bạn đã có onChange handler cho từng Trình chỉnh sửa trường, tôi không thấy lý do tại sao bạn không thể di chuyển trạng thái lên thành phần FormEditor và chỉ chuyển một cuộc gọi lại từ đó sang FieldEditors sẽ cập nhật trạng thái gốc . Điều đó có vẻ giống như một cách React-y hơn để làm điều đó, với tôi.

Something dọc theo dòng này có lẽ:

var FieldEditor = React.createClass({ 
    handleChange: function(event) { 
    var text = event.target.value; 
    this.props.onChange(this.props.id, text); 
    }, 

    render: function() { 
    return (
     <div className="field-editor"> 
     <input onChange={this.handleChange} value={this.props.value}/> 
     </div> 
    ); 
    } 
}); 

var FormEditor = React.createClass({ 
    getInitialState: function() { 
    return {}; 
    }, 
    handleFieldChange: function(fieldId, value) { 
    var newState = {}; 
    newState[fieldId] = value; 

    this.setState(newState); 
    }, 

    render: function() { 
    var fields = this.props.fields.map(function(field) { 
     var props = { 
     id: field, 
     onChange: this.handleFieldChange, 
     value: this.state[field] 
     } 
     return <FieldEditor {...props} /> 
    }, this); 

    return (
     <div> 
     {fields} 
     <div>{JSON.stringify(this.state)}</div> 
     </div> 
    ); 
    } 
}); 

var App = React.createClass({ 
    render: function() { 
    var fields = ["field1", "field2", "anotherField"]; 

    return (
     <FormEditor fields={fields}/> 
    ); 
    } 
}); 


React.render(<App/>, document.body); 

http://jsbin.com/fabonujenu/8/edit

Chỉnh sửa: Thay vì đi qua các yếu tố FieldEditor như trẻ em FormEditor tôi Chỉ cần vượt qua một danh sách các fieldIds và tạo chúng trong FormEditor để thay thế. Điều này làm cho nó dễ dàng hơn để tự động thêm FieldEditors và làm cho phương thức render của FormEditor ít thắng hơn.

+0

Đây là hữu ích cho onChange, nhưng không nhiều trong onSubmit. –

+1

@ 190290000RubleMan Tôi không chắc ý bạn là gì, nhưng vì các trình xử lý onChange trên các trường riêng lẻ đảm bảo rằng bạn luôn có sẵn dữ liệu biểu mẫu đầy đủ trong tiểu bang của bạn trong thành phần FormEditor, onSubmit của bạn sẽ bao gồm một cái gì đó như 'myAPI. SaveStuff (this.state); '. Nếu bạn xây dựng thêm một chút, có lẽ tôi có thể cung cấp cho bạn câu trả lời tốt hơn :) –

+0

Giả sử tôi có một biểu mẫu với 3 trường thuộc loại khác nhau, mỗi trường có xác thực riêng. Tôi muốn xác thực mỗi người trước khi gửi. Nếu xác thực không thành công, mỗi trường có lỗi sẽ được đặt lại. Tôi đã không tìm ra cách để làm điều này với giải pháp đề xuất của bạn, nhưng có lẽ có một cách! –

121

Nếu bạn muốn truy cập trạng thái con của một thành phần, bạn có thể gán một thuộc tính được gọi là ref cho mỗi đứa trẻ. Thuộc tính này nhận hàm gọi lại được chuyển qua tham chiếu đến thành phần được đính kèm. Lệnh gọi lại này được thực hiện ngay lập tức sau khi thành phần được gắn kết hoặc tháo lắp.

Ví dụ:

ES5:

<FieldEditor 
    ref={function(fieldEditor1){this.fieldEditor1 = fieldEditor1;}} 
    {...props} 
/> 

ES6:

<FieldEditor 
    ref={(fieldEditor1) => {this.fieldEditor1 = fieldEditor1;} 
    {...props} 
/> 

Trong những ví dụ các tài liệu tham khảo được lưu trữ trên các thành phần cha mẹ. Để gọi thành phần này trong mã của bạn, bạn có thể sử dụng:

this.fieldEditor1 

và sau đó sử dụng this.fieldEditor1.state để nhận trạng thái.

Một điều cần lưu ý, hãy chắc chắn thành phần con quý vị đã trả lại trước khi bạn cố gắng truy cập vào nó^_^

Nếu bạn muốn đọc thêm về Phản ứng hữu ref của, hãy kiểm tra page này từ Facebook.

Đảm bảo bạn đọc phần "Don't Overuse Refs" cho biết bạn không nên sử dụng số state của trẻ để "thực hiện mọi thứ".

Hope this helps^_^

Chỉnh sửa: Thay đổi câu trả lời cho sử dụng refs callback như trái ngược với refs chuỗi như refs chuỗi có thể sẽ được loại bỏ trong một thông cáo React.js tương lai (xem Refs and the DOM để biết thêm chi tiết).

+5

Cũng gọn gàng chút nhỏ, bạn có thể gọi các chức năng từ 'this.refs.yourComponentNameHere'. Tôi đã thấy nó hữu ích cho việc thay đổi trạng thái thông qua các hàm. Ví dụ: 'this.refs.textInputField.clearInput();' –

+7

Cẩn thận (từ tài liệu): * Tham chiếu là cách tuyệt vời để gửi thư đến một cá thể con cụ thể theo cách bất tiện để thực hiện qua streaming Phản ứng 'props' và' state'. Tuy nhiên, chúng không phải là sự trừu tượng của bạn để lưu dữ liệu thông qua ứng dụng của bạn. Theo mặc định, hãy sử dụng dòng dữ liệu Reactive và lưu 'ref' cho các ca sử dụng vốn không có phản ứng. * – Lynn

+2

Tôi chỉ nhận được trạng thái được định nghĩa bên trong hàm tạo (không cập nhật trạng thái) –

Các vấn đề liên quan