2015-01-09 14 views
110

私は、次の構造を持っている:Reactで子供の状態にアクセスするには?

FormEditorが - 複数のFieldEditor FieldEditorを保持している - フォームのフィールドを編集し、ボタンがFormEditor内クリックされたとき、それは状態

だでそれについての様々な値を保存し、私がしたいですすべてのFieldEditorコンポーネントのフィールドに関する情報、その状態にある情報、FormEditor内のすべての情報を収集することができます。

フィールドの情報をFieldEditorの状態外に格納し、その代わりにFormEditorの状態にすると考えました。しかし、それはがそれぞれのコンポーネントを変更し、その状態に情報を保存するときに、そのコンポーネントのそれぞれを受信することを必要とします。

代わりに子どもの状態にアクセスすることはできませんか?それは理想的ですか?

+4

*「子供の状態にアクセスすることはできますか?それは理想的ですか?」*いいえ状態は内部的なものであり、外部に漏れてはいけません。あなたはあなたのコンポーネントのアクセサメソッドを実装することができますが、それは理想的ではありません。 –

+0

@FelixKlingそれでは、子どもと親のコミュニケーションが理想的な方法はイベントだけであることを示唆していますか? –

+3

はい、イベントは片道です。 Fluxのような一方向のデータフローを促進させる:https://facebook.github.io/flux/ –

答えて

69

個々のFieldEditorsのonChangeハンドラが既にある場合は、FormEditorコンポーネントまで状態を移動してそこからコールバックをFieldEditorsに渡して親状態を更新できない理由がわかりません。それは、私にとってもっとやりがいのある方法のようです。

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

編集:おそらく、この線に沿って

何か代わりにFormEditorの子としてFieldEditor要素を渡すので、私はちょうどfieldIdsのリストを渡して、代わりにFormEditorでそれらを作成します。これにより、FieldEditorを動的に追加することが容易になり、FormEditorのレンダリングメソッドをより少なくすることができます。

+0

これはonChangeには便利ですが、onSubmitではそれほど多くはありません。 –

+1

@ 190290000RubleMan個々のフィールドのonChangeハンドラは、FormEditorコンポーネントの状態で常に完全なフォームデータを使用できることを確認しているため、onSubmitにはmyAPIなどが含まれています。 SaveStuff(this.state); '。もう少し詳しく説明すると、おそらく私はあなたに良い答えを与えることができます:) –

+0

私は3つの異なるタイプのフィールドを持つフォームがあり、それぞれ独自の検証があるとします。私は提出する前にそれぞれを検証したいと思います。検証に失敗すると、エラーのある各フィールドが再レンダリングされます。私はあなたの提案されたソリューションでこれを行う方法を考え出していないが、おそらく方法がある! –

121

コンポーネントの子の状態にアクセスする場合は、各子にrefというプロパティを割り当てることができます。このプロパティは、添付されたコンポーネントへの参照を渡されるコールバック関数をとります。このコールバックは、コンポーネントがマウントまたはアンマウントされた直後に実行されます。例えば

ES5:

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

ES6:これらの例で

​​3210

基準は、親コンポーネントに格納されています。あなたのコード内でこのコンポーネントを呼び出すには、使用することができます。その後、

this.fieldEditor1 

と状態を取得するためにthis.fieldEditor1.stateを使用しています。注意すべき

一つのこと、あなたがそれにアクセスしようとする前に、あなたの子コンポーネントをレンダリングしていることを確認してください^ _^

あなたはについての詳細を読みたい場合の参照プロパティを反応させるのは、Facebookからこのpageをチェックしてください。

子供のstateを「起こらせる」ために使用しないでくださいという「Don't Overuse Refs」セクションを必ず読んでください。

希望はこのことができます^ _^

編集:文字列、参考文献が(詳細はRefs and the DOMを参照)、将来のReact.jsのリリースで削除される可能性があるとして、文字列、参考文献とは対照的に、コールバック、参考文献を使用するように答えを変更しました。

+5

また、きちんとした小さなおしゃぶり、 'this.refs.yourComponentNameHere'から関数を呼び出すことができます。関数を介して状態を変更すると便利だとわかりました。 例:'this.refs.textInputField.clearInput(); –

+7

注意:* Refsは、経由するのが面倒な方法で特定の子インスタンスにメッセージを送信するための素晴らしい方法です反応的な 'props'と' state'をストリーミングします。ただし、アプリケーションでデータを流すための抽象化ではありません。デフォルトでは、Reactiveデータフローを使用し、本質的に非反応性のユースケースに対しては 'ref'を保存します。* – Lynn

+2

コンストラクタ内で定義された状態のみを取得します(最新状態ではありません) –

関連する問題