2016-08-08 24 views
4

Reduxアプリケーションでインスタンスごとに1つのストアを作成すると便利なことがあります。私はdispatchする方法を疑問に思うReduxでインスタンスごとに1つのストアを作成する方法は?

:私は要旨で、すでにこの質問をしたが、私はStackOverflowのは、この質問のためのより良い場所だと思うhttps://gist.github.com/gaearon/eeee2f619620ab7b55673a4ee2bf8400

:Reduxの自身の作成者は、これを実現する方法について説明要旨を作成しましたコンポーネント自身の特別な店舗への行動?各<SubApp />(およびその子コンポーネント)のstore-<Provider />のプロンプトにアクセスする方法はありますか?

例:リモートサーバーからデータを取得した後にdispatchを呼び出すAPIクラスがいくつかあります。しかし、私は "普通"のストアをインポートすることができないので、カスタムストアを他のクラス/ファイル/サービスで利用できるようにするための最良の方法は何でしょうか?

アップデート1

だから私はそれが働いてしまったが、私はそれが本当に汚いやり方(コード内部UGLY?コメントを気)だと思う:

プロバイダ:

店舗あたりの作成コンストラクタ内にストアを作成してインスタンスを作成します。

export default class OffersGridProvider extends React.Component { 
    constructor(props) { 
    super(props) 
    this.store = createStore(reducers); 
    } 

    render() { 
    return (
     <Provider store={this.store}> 
     <OffersGridContainer offers={this.props.offers} /> 
     </Provider> 
    ); 
    } 
} 
コンテナ:

class OffersGridContainer extends React.Component {  
    componentDidMount() { 

    // UGLY??? 
    const { dispatch } = this.props; 

    let destinationIds = []; 
    this.props.offers.forEach((offer) => { 
     offer.to.forEach((destination) => { 
     destinationIds.push(destination.destination); 
     }); 
    }); 

    // MORE UGLY??? 
    destinationsApi.getDestinations(dispatch, destinationIds); 
    } 

    render() { 
    return (
     <OffersGridLayout destinations={this.props.destinations} /> 
    ); 
    } 
} 

const mapStateToProps = function(store) { 
    return { 
    destinations: store.offersGridState.destinations 
    }; 
} 

export default connect(mapStateToProps)(OffersGridContainer); 

APIメソッド:

プロバイダは、私はちょうどこのインスタンスの店にアクションをディスパッチするために使用することができます私のOffersGridContainerこのストアのdispatch方法を注入

APIメソッドの引数として渡したdispatchメソッドを使用してください:

class OffersGridContainer extends React.Component {  
    componentDidMount() { 
    let destinationIds = []; 

    this.props.offers.forEach((offer) => { 
     offer.to.forEach((destination) => { 
     destinationIds.push(destination.destination); 
     }); 
    }); 

    this.props.getDestinations(destinationIds); 
    } 

    render() { 
    return (
     <OffersGridLayout destinations={this.props.destinations} /> 
    ); 
    } 
} 

const mapStateToProps = function(store) { 
    return { 
    destinations: store.offersGridState.destinations 
    }; 
} 

const mapDispatchToProps = function(dispatch) { 
    return { 
    getDestinations: function(ids) { 
     return destinationsApi.getDestinations(dispatch, ids); 
    } 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(OffersGridContainer); 

アップデート3(最終的な答え)

今すべて:私のContainerは次のようになりますので、アップデート2

ちょうど、コメントでは約mapDispatchToPropsヒントを受けた10

export function getDestinations(dispatch, ids) { 
    const url = $('meta[name="site-url"]').attr('content'); 

    const filter = ids.map((id) => { 
    return `filter[post__in][]=${id}`; 
    }).join('&'); 

    return axios.get(`${url}/wp-json/wp/v2/destinations?filter[posts_per_page]=-1&${filter}`) 
    .then(response => { 
     dispatch(getOffersGridSuccess(response.data)); 
     return response; 
    }); 
} 

作品!ここでは、コードには:

プロバイダ:

export default class OffersGridProvider extends React.Component {  
    constructor(props) { 
    super(props) 
    this.store = createStore(reducers, applyMiddleware(thunk)); 
    } 

    render() { 
    return (
     <Provider store={this.store}> 
     <OffersGridContainer offers={this.props.offers} /> 
     </Provider> 
    ); 
    } 
} 

コンテナ:

class OffersGridContainer extends React.Component { 
    componentDidMount() { 
    const destinationIds = this.props.offers.reduce((acc, offer) => { 
     return [...acc, ...offer.to.map(d => d.destination)]; 
    }, []); 

    this.props.getDestinations(destinationIds); 
    } 

    render() { 
    return (
     <OffersGridLayout destinations={this.props.destinations} /> 
    ); 
    } 
} 

const mapStateToProps = function(store) { 
    return { 
    destinations: store.offersGridState.destinations 
    }; 
} 

const mapDispatchToProps = function(dispatch) { 
    return { 
    getDestinations: function(ids) { 
     return dispatch(destinationsApi.getDestinations(ids)); 
    } 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(OffersGridContainer); 

APIメソッド:

export function getDestinations(ids) { 
    return function(dispatch) { 
    const url = $('meta[name="site-url"]').attr('content'); 

    const filter = ids.map((id) => { 
     return `filter[post__in][]=${id}`; 
    }).join('&'); 

    return axios.get(`${url}/wp-json/wp/v2/destinations?filter[posts_per_page]=-1&${filter}`) 
     .then(response => { 
     return dispatch(getOffersGridSuccess(response.data)); 
     }); 
    } 
} 

+0

connect' '2番目のパラメータがあります:' mapDispatchToProps'あなたが維持することができますコンポーネントはディスパッチを認識しません。 –

+0

ありがとう!私の更新を見直してください。 – Slevin

+0

次のアップデート:ミドルウェアとして 'thunk'を使用して、' dispatch'を引数として渡して、私の 'getDestinations'メソッドの中で関数を返す必要はありません。 – Slevin

答えて

1

の代わりにコンポーネントで直接API呼び出しを行う場合は、redux-thunkパッケージを使用することをお勧めします。

次は、コンポーネントにアクションクリエーター機能を注入するために、connect機能に2つ目の引数としてmapDispatchToProps関数を渡す必要があります。

import { getDestinations } from '../actions'; 

class OffersGridContainer extends React.Component {  
    componentDidMount() { 
    // Tip. 
    const destinationIds = this.props.offers.reduce((acc, offer) => { 
     return [...acc, ...offer.to.map(d => d.destination)]; 
    }, []); 

    // instead `destinationsApi.getDestinations(dispatch, destinationIds)` 
    // call action creator function 
    this.props.getDestinations(destinationIds); 
    } 

    render() { 
    return (
     <OffersGridLayout destinations={this.props.destinations} /> 
    ); 
    } 
} 

const mapStateToProps = function(store) { 
    return { 
    destinations: store.offersGridState.destinations 
    }; 
} 

const mapDispatchToProps = function(dispatch) { 
    return { 
    // this function will be available in component as 
    // `this.props.getDestinations`. 
    getDestinations: function(destinationIds) { 
     dispatch(getDestinations(destinationIds)); 
    } 
    }; 
} 

export default connect(mapStateToProps, mapDispatchToProps)(OffersGridContainer); 
+0

ありがとう!私は最初のアプローチを試みましたが、店舗は変わりません。 'SubApp'を数回レンダリングしたいのですが、データが1つの' SubApp'で変更されると、 'SubApp'の他のインスタンスもすべて更新されます。 'customStore'は' constructor'の内部で作成しなければならないと思いますが、エクスポートする可能性が失われてしまいます。私は少しフィドルを作成し、新しいコメントのリンクを追加するつもりです。 – Slevin

+0

@スレーン、オフィール、それはフィドルで理解する方が簡単です。 – 1ven

+0

ああ、私はそれを理解しました(しかし、私はこれが "ベストプラクティス"だとは思わない...)。私の質問を更新するつもりです。 – Slevin

関連する問題