2016-06-15 9 views
0

親の<MessageBox />要素があり、状態に格納されたmessagesのリストを含んでいます。 messagemessagesの場合、message.subjectmessage.bodyの各フィールドを持つ内に<Message />要素が作成されます。ユーザーはmessage.subjectmessage.bodyを編集できます。完了すると、messageオブジェクトはprops.updateHandler()を通して<MessageBox />に返され、親のメッセージ状態を維持します。ReactJS:親と子の間のデータ状態を維持します

私の現在のアプローチでは、MessageBoxの状態にメッセージデータを格納しており、render()関数では、<Message />要素を作成し、それぞれにコールバックを渡してデータの変更を送り返します。コールバックでは、<Message />要素のそれぞれから更新されたデータがMessageBoxの状態に更新されます。この理由は、最近更新されたすべてのデータを1か所に保存するためです。上記の方法は、<Message />shouldComponentUpdate()メソッドがオーバーロードされていない場合(無限再帰)に大混乱を引き起こします。

これにはより良いアプローチがありますか?私は、組み込みのメソッドをオーバーライドして全体を安定に保つために、たくさんのコードを書く必要があります。私がFlux/Reduxのために行くつもりはないので、これにはReact-onlyアプローチがありますか?

編集:混乱が多いので、最小限のコードを追加しています。

class Message extends React.Component { 
    constructor(props) { 
     this.state = { 
      subject: this.props.subject, 
      body: this.props.body, 
      type: this.props.type, 
      messageIndex: this.props.messageIndex 
     }; 
    } 

    componentDidUpdate() { 
     this.props.updateHandler(messageIndex, { 
      subject: this.state.subject, 
      body: this.state.body, 
      type: this.state.type 
     }); 
    } 

    render() { 
     return (
      <div> 
       <input 
        type="text" 
        defaultValue={this.state.subject} 
        onBlur={e => this.setState({subject: e.target.value})} /> 

       <input 
        type="text" 
        defaultValue={this.state.subject} 
        onBlur={e => this.setState({body: e.target.value})} /> 

       <select 
        type="text" 
        value={this.state.subject} 
        onChange={e => this.setState({type: e.target.value})}> 
        <option>Type 1</option> 
        <option>Type 2</option> 
       </select> 
      </div> 
     ) 
    } 
} 

class MessageBox extends React.Component { 
    constructor(props) { 
     this.state = { 
      messages: aListOfMessageObjects 
     } 
    } 

    updateHandler(message) { 
     // Message update happens here and returns a list updatedMessages 
     this.setState({ 
      messages: updatedMessages 
     }); 
    } 

    render() { 
     let _this = this; 

     var messagesDOM = this.state.messages.map((m) => { 
      return (
       <Message 
        message={m} 
        updateHandler={_this.updateHandler.bind(_this)} /> 
      ); 
     }) 

     return (
      <div> 
       {messagesDOM} 
      </div> 
     ); 
    } 
} 
+1

親コンポーネントにmessage.subjectとmessage.bodyが必要な理由を記述しませんでした。あなたがそこにそれを必要としないならば、子コンポーネントにそれらを小道具として渡し、それらから子供の状態を作ることは完全に有効です。 – Maggie

+1

"コールバックでは、要素のそれぞれから更新されたデータがMessageBoxの状態に更新されます。このコールバックがトリガされると、このコールバックは、ユーザーがメッセージを編集した場合にのみトリガーされます。私はこのような再帰的なループを見ることができません。いくつかのコード実装を提供できますか?MessageBox&Messageの実装を誤解する可能性があります。 –

+0

@Maggie 'message.body'と' message.subject'は 'message'の一部であり、AJAX経由でサーバに送り返されるか、他の' messages'とともにバルク挿入または更新されます。だからこそ私はすべての 'messages'データが1つの場所に必要です。 –

答えて

1

それは助けることができる場合は、thinking-in-reactをお読みください。 UIの更新でデータが失われないようにするには、データがどのように変化するかを説明します。

React ToDo MVCは、子供たちに自分の親から小道具を渡す方法を知るために、あなたに実際のケースで良い練習に反応

の例を提供しますcontrolled-componentsをお読みください。各入力にvalueonBlurを使用する必要があります。いずれのonBlurイベントでも、の代わりにthis.props.updateHandlereがパラメータとして呼び出されます。

1
  1. MessagecomponentDidUpdate()からMessageBoxにコールバックをしないでください。 Messageのアクションからコールバックを直接行います。
  2. Messageコンポーネントには状態はまったく必要ありません。親の状態を正しく更新すると、小道具は興味のある値を保持します。コンポーネントが再描画されますが、親のSETSTATEに別の呼び出しを行うことはありません道

    <input type="text" 
         defaultValue={this.props.subject} 
         onBlur={e => this.updateSubject(e.target.value)} /> 
    
        updateSubject: function(newSubjectValue) { 
         this.props.updateHandler(messageIndex, { 
          subject: newSubjectValue, 
          body: this.props.body, 
          type: this.props.type 
        }); 
        } 
    

    :あなたが必要なもの

のようなものです。

+0

これを試してみます。 –

関連する問題