2016-05-01 15 views
4

Ajax呼び出しでreactを使用するという面白いケースがあります。ajax呼び出しライフサイクルを持つ反応コンポーネント

文脈に入れると、3つのタブを持つアコーディオンがあります。 Accordionの反応コンポーネントを初期化した後、最初のタブが最初に開き、残りの部分が閉じられます。 すべてのタブには、次のようになり、それの体いわゆるDictionaryCallコンポーネントであり:小道具とReact docs初期状態設定に応じて、すべての

return class DictionaryCall extends React.Component { 

     constructor (props) { 
      super(); 
      this.state = { 
       word: '', 
       data: [], 
       error: false, 
       nodata: false, 
       initialLoaded: props.load 
      } 
     } 

     componentDidMount() { 
      if(this.state.initialLoaded){ 
       this.callAjax(); 
      } 
     } 

     componentWillReceiveProps (nextProps) { 
      if(nextProps.load){ 
       this.setState({initialLoaded: true}); 
       this.callAjax(); 
      } 
     } 

     callAjax() { 
      $.ajax({ 
       url: this.props.url, 
       dataType: 'json', 
       catche: false, 
       method: 'POST', 
       data: {word: this.props.word}, 
       success: function(data){ 
        if(!data.length){ 
         this.setState({nodata: true}); 
        } else { 
         this.setState({data: data}); 
        } 
       }.bind(this), 
       error: function(xhr, status, error){ 
        console.log(this.props.url, status, error.toString()); 
        this.setState({error: true}); 
       }.bind(this) 
      }); 
     } 

     render() { 
      let body, 
       error = this.state.error; 

      if(this.state.nodata){ 
       body = <div>No definition found</div> 
      } else { 
       body = <DataTab data={this.state.data} title={this.props.word}/> 
      } 

      return (
       <div className="dictionary-call"> 
        {body} 
        {error ? <ServerError onClick={this.callAjax.bind(this)}/> : null} 
       </div> 
      ) 
     } 
    }; 

拳あなたはそれが唯一のコンポーネントの初期化のためだ、明示的に指定するまで、アンチパターンです。

コンストラクタで見ることができるように、initialLoadedの状態をprops.loadに設定しています。 props.loadtrueとして最初のAccordionタブに渡していますが、最初にロードする必要があります。

componentDidMountメソッドが呼び出され、initialLoaded状態をチェックします。 trueに設定されている場合、単にajaxを呼び出してコンポーネントを再レンダリングします。

今やトリッキーなビットです。 componentWillReceivePropsメソッド。私は、ユーザーがアコーディオンタブをクリックして開くときにコンポーネントがnextProps.loadを受け取ることを期待しています。次に、をtrueの値のコンポーネントに渡します。

私の質問はcomponentWillReceivePropsといいますか?this.callAjax()に電話するのはいいですか?この場合、initalLoaded状態を作成するのは少し意味がないようです。代わりにprops.loadをベースにして、shouldComponentUpdateと呼んではいけませんか?

それとも私がinitalLoaded状態に固執し、componentWillUpdateまたはcomponentDidUpdateを使用する必要があります。

心に留めておいてください。初めてアコーディオンタブを開いたときに、ajaxコールを1回呼び出すだけです。

ありがとうございます!

+0

このアーキテクチャを使用することに限定していますか?私は、アコーディオンのコンポーネントの中でajaxを呼び出すことによってアンチパターンを永続させると思います。アコーディオンコンポーネントは、データの表示のみを処理し、何も取得しないようにしてください。あなたの最上位レベルのコンポーネントでさえ、フェッチやアコーディオンの状態を上げて扱うことで、これはずっと簡単でしょうか? – azium

+0

いいえ、別のエンドポイントから各タブをフェッチしたいと思います。さらに、ユーザーがタブヘッダーをクリックしたときにのみ、 'this.props.open'に基づいてフェッチをトリガーします。だから私にとってはまったく問題ない。 – matewilk

+1

これはあなたにとってうれしいことですが、私はあなたにこれを扱うもっと「リアクト」な方法を検討することを奨めます。フラックススタイルの実装では、コンポーネントがajax呼び出しを行うことはなく、アクションレイヤーですべて処理されます。これにより、コンポーネントの動作の見栄えを完全に重視することができます。 – azium

答えて

5

私は自分の質問に答えたいと思っています。誰かを助けることを願っています。

解決策は非常に簡単で清潔です(私の意見では)。

 componentDidMount() { 
      if(this.state.initialLoaded){ 
       this.callAjax(); 
      } 
     } 

     componentWillReceiveProps (nextProps) { 
      if(nextProps.load){ 
       this.setState({initialLoaded: true}); 
      } 
     } 

     componentWillUpdate (nextProps, nextState) { 
      if(this.state.initialLoaded !== nextState.initialLoaded) { 
       this.callAjax(); 
      } 
     } 

このコードは、コンポーネントのすべてのインスタンスに適用され、それが最初のアコーディオンタブ(最初に開いている)、またはタブの残りの子であるならばどんなには(最初は閉じています)。

componentDidMountメソッドでは、コンポーネントがAjax呼び出しを行う必要があるかどうかを確認しています。初期化中にthis.props.openthis.state.initialLoaded状態をtrueに設定した場合、ajax呼び出しが行われます。そうでなければもちろんそうではありません。

ユーザーが他のタブをクリックすると、コンポーネントはcomponentWillReceivePropsの小道具を待っています。ここでは、loadフィールドがtrueの場合にのみデータをロードする可能性があるため、nextProps.loadがtrueの場合にのみ状態を設定しています。

最後に、componentWillReceivePropsの条件が満たされている場合は、this.state.initialLoadedが変更されているかどうかを確認しています。nextProp.loadがtrueの場合にのみ変更できるため、Ajaxリクエストを何度も呼び出すことができなくなります(状態が真から偽に変わるとき)。

このように、タブを初めて開いたとき、または最初に開いたときにのみ、Ajaxリクエストを呼び出します。

これは簡単です!

+0

シンプルで効果的です。ありがとうございました –

関連する問題