2016-09-23 17 views
0

私はこれまで使用していなかったReact-Reduxを使用してメトリクスページを作成しています。1つのイベントを使用してreduxで複数のajaxリクエストをトリガーする

<input id=start_date /> 
<input id=end_date /> 
<button id=submit onClick={ this.props.fetchChartData() }/> 
<Chart1 /> 
<Chart2 /> 

店の構造はこれです:

基本的な構造は、このようなものであるサンクを使用して

dates 
    start_date: "2016-09-16" 
    end_date: "2016-09-16" 
charts 
    Chart1 
     api_func: "get_supported_events" 
     fetching: false 
     fetched: false 
     data: null 
     error: null 
    Chart2 
     api_func: "get_events_closed" 
     fetching: false 
     fetched: false 
     data: null 
     error: null 

、私の行動は今、これらの機能が含まれます。

function getStateURL(state){ 
    return state.charts.Chart1['api_func']; 
} 

export function fetchChartData(){ 
    return (dispatch, getState) => { 
     dispatch(fetchChartDataStart()); 
     return fetch(getStateURL(getState())) 
      .then((response) => response.json()) 
      .then((json) => dispatch(receiveChartData(json))) 
      .catch((err) => dispatch(fetchChartDataError(err))); 
    } 
} 

問題は、私はablでなければならないように感じるので、私はチャート名をハードコードしたくありませんすべてのチャートが同じことをする必要があるため、1つのアクションを記述します。

私が推測できる最良の解決策は、チャートのコンポーネントがリッスンできるイベントをトリガーするようにすることです。状態が要求されると、状態全体ではなくチャートの部分に制限されます。反応コンポーネントが他のコンポーネントによってキャッチされる可能性のあるイベントをトリガーする方法はありますか?

+0

:あなたのような何かを行うことができますか?また、チャート名を「ハードコーディング」している場所もありますか? '['api_func']'を意味しますか? – ajmajmajma

+0

今、私はボタンからfetchChartDataを呼び出しています。別のURLを取得するためには、すべてのグラフが必要です。私はボタンがアプリケーション内にあるチャートに無関心であるようにしたい。すべてのチャートを更新する必要があることを通知する必要があります。 ハードコードはgetStateURLにあります。ここではChart1のapi_funcを指定します。 – carpenterwb

+0

すべてのチャートを渡して文字列をループするのではなく、すべての可能なチャートが分かっている場合は、独自のマッピングを作成するのはなぜでしょうか。または、バックエンドにアクセスできる場合は、チャートのリストをパラメータとして取る単一の呼び出しにしてください。 – ajmajmajma

答えて

0

あなたが提案している解決策は、ストアがEventEmitterのインスタンスに過ぎない場合、古いFluxモデルのように見えます。フラックスを用い

それはすぐに明らかにされていませんが、あなたはRedux<Chart />

よう
class Chart extends Component { 
    componentDidMount() { 
    store.addEventListener('fetchData', this.fetchData); 
    } 

    componentWillUnmount() { 
    store.removeEventListener('fetchData', this.fetchData); 
    } 

    this.fetchData() { 
    api.fetchChartData(store.get('chart1.url'); 
    } 

    render() { 
    ... 
    } 
} 

を作ることができます。それはむしろ定数としてどこかURLを、このために高次のコンポーネントを実装しておく価値がある、

class Chart1 extends Component { 
    componentWillReceiveProps(nextProps) { 
    if (!nextProps.fetching && !nextProps.fetched) { 
     const { fetchData, url } = this.props; 
     fetchData(url); 
    } 
    } 

    render() { 
    ... 
    } 
} 

export default connect(state => ({ 
    fetching: state.Chart1.fetching 
    fetched: state.Chart1.fetched 
    url: state.Chart1.url 
}), { 
    fetchData 
})(Chart1) 

/action.js

export function fetchChartData(url){ 
    return (dispatch) => { 
     dispatch(fetchChartDataStart()); 
     return fetch(url) 
      .then((response) => response.json()) 
      .then((json) => dispatch(receiveChartData(json))) 
      .catch((err) => dispatch(fetchChartDataError(err))); 
    } 
} 

でのすべての<Chart />のコンポーネントで同様の機能を考慮:しかし、それを行うことが可能ですストアよりも。 Chart.jsx

export const fetchData = (url) => (Wrapped) => { 
    class Wrapper extends Component { 
     componentWillReceiveProps(nextProps) { 
     if (!nextProps.fetching && !nextProps.fetched) { 
      const { fetchData, url } = this.props; 
      fetchData(url); 
     } 
     } 

     render() { 
     return <Wrapped {...this.props} /> 
     } 
    } 

    return connect(null, { fetchData })(Wrapper); 
} 

好き、それを使用します。

import { chart1Url } from '.../someconstants'; 
import { fetchData } from '/hocs/fetchData' 

const Chart1 =() => { 
    return <div>...</div>; 
} 

export default fetchData(chartUrl)(Chart1); 

を、それは可能ですが、私はまだ最善の解決策は、定数ファイルのURLを格納すること、および他のモジュールでAPI関数を置くと思います。なぜだけではなく、あなたはそれがfetchChartDataアクションに必要な情報を渡す ./api/fetchData.js

export function fetchData(url) { 
    return new Promise((resolve, reject) => 
    fetch(url) 
     .then((response) => response.json()) 
     .then((json) => resolve(json)) 
     .catch((err) => reject(err)); 
} 

./actions.js

import { fetchData } from '../api/fetchData'; 
import { urls } from '.../constants'; 

export function fetchChartData(){ 
    return (dispatch) => { 
     dispatch(fetchChartDataStart()); 
     return Promise.all(urls.map((url) => 
      fetchData(url) 
      .then((json) => dispatch(receiveChartData(json))) 
      .catch((err) => dispatch(fetchChartDataError(err)))); 
    } 
} 
+0

これは私が必要とするものにかなり近いようですが、今試してみてください。好奇心から、この権利を得るための私の原動力は、新しいチャートが要求されたときに次の開発者が書き込んだ新しいチャートファイルにドロップしてチャートをメインのJSXに追加できるようにすることです。そのためには、コンポーネント自体にURLを挿入します。 URLを別のファイルに置くことには利点がありますか? – carpenterwb

+0

通常、URLは定数であるため、別のファイルに入れるのが理にかなっています。これにより、データ(URL)とコンポーネント自体が分離されます。しかし、これらのことは間違いなくアプリごとに異なります。あなたは開発者として最高の裁判官になるでしょう。あなたの状況では、おそらくコンポーネント内のURLが意味をなさないでしょう。しかし、高次コンポーネントのソリューションを使用することはできません。 – yjcxy12

関連する問題