2017-08-16 5 views
1

かなり単純な使用例:ajaxリクエストを実行してリストを更新するアクション/イベントがあります。React/Reduxでチェーンアクションを配置する場所

問題は、私がどのようにページが変更されたときが新しいリストの要求をキックオフする(具体的には、わからない。

Reduxのストア

const defaultStore = { 
    list: [], 
    page: 1  
}; 

ラッパーコンポーネントである

const wrapper = props => (
    <div> 
    <List {...props}> {/* This list should have page controls */} 
     <PageControls {...props} /> 
    </List> 
    <List /> {/* This list should not have page controls */} 
    </div> 
); 

Listコンポーネント

const List = props => (
    <div> 
    {props.children} {/* render page controls if present */} 
    {props.items.map((item, k) => <div key={k}>item</div> 
    </div> 
); 

ポケットベルを制御し、この時点で、コンポーネント

const PageControls = props => (
    <div> 
    <span onClick={props.changePage(-1)}>Backward</span> 
    <span onClick={props.changePage(1)}>Forward</span> 
    </div> 
); 

actionCreator

function changePage(delta) { 
    return { 
    type: 'CHANGE_PAGE', 
    delta 
    }; 
} 

// utilizes react-thunk middleware 
function getList(page = 1) { 
    return dispatch => 
    axios.get(`/path/to/api?page=${page}`) 
     .then(res => dispatch(updateList(res.data)); 
} 

function updateList(newList) { 
    return { 
    type: 'UPDATE_LIST', 
    newList 
    }; 
} 

減速

function reducer(state = {}, action) { 
    switch(action.type) { 
    case 'CHANGE_PAGE': 
     return {...state, page: state.page + action.delta}; 
    case 'UPDATE_LIST': 
     return {...state, list: action.newList}; 
    default: 
     return state; 
    } 
} 

私は物事のカップルを行うことができます - トリガすべきこと私はすべてのactionCreatorを作ることができますリストの更新ディスパッチアクション:

function changePage(delta) { 
    return dispatch => { 
    dispatch({ 
     type: 'CHANGE_PAGE', 
     delta 
    }); 

    return dispatch(getList(store.getState() + delta)); 
    } 
} 

これは面倒です。今私はstoreを取得するだけでなく、リストに影響を与えるすべてのactionCreatorをサンクにする必要があります。私は考えることができる

唯一の他の事は、ページへの変更を監視し、別のgetListアクションをキックオフするためにどこかに私の<List>コンポーネントの使用store.subscribeを持つことですが、私が何をするかの理解を動かしてるようこれもそうですし、 Reduxから私のReactコンポーネントへの状態変化を引き起こしません。

アイデア?

答えて

1

あなたのアプローチを変更する必要があります。私は、ページを変更してリストを取得するための2つのアクションを行う理由は見当たりません。ボタンをクリックするだけで、次のページ番号を渡して、getPage()アクションを送信することができます。これは、アイテムのリストを取得し、ページを更新する必要があります。

あなたの店では、現在のページを追跡する必要があるので、ページが更新されるたびにgetPage()引数の値も更新されます。例えば

(現在のページがAPIから取得されていないと仮定):

function getPage(page = 1) { 
    return dispatch => 
    axios.get(`/path/to/api?page=${page}`) 
     .then(res => dispatch(updatePage(res.data, page)); 
} 

function updatePage(newList, currentPage) { 
    return { 
    type: 'UPDATE_PAGE', 
    newList, 
    currentPage, 
    }; 
} 

及び格納するために必要な構成要素を接​​続する、あなたのケースでは、それはListPageControls成分であろう。

const PageControls = props => (
    <div> 
    <span onClick={props.getPage(props.currentPage - 1)}>Backward</span> 
    <span onClick={props.getPage(props.currentPage + 1)}>Forward</span> 
    </div> 
); 

これにより、シンプルでクリーンなコードを維持できます。また、関連するコンポーネントではなく、複数のコンポーネントからトリガできます。

+0

ありがとうございます。私の唯一の疑問は、還元がどのように使われるのかということでしょうか?私は基本的に非同期を実行し、アクションをディスパッチする関数を呼び出しています。これは、コンポーネント内で非同期呼び出しを実行することと大きく異なるとは思われません。 Reduxのアイデアは、状態を取得した後にアクション送信がディスパッチされるのではなく、アクション提出に応答するということだと思いました。 – diplosaurus

+0

はい。 reduxのアイデアは、アプリケーション内のすべてのコンポーネントからグローバルストアを利用できるようにすることです。それはまた、還元行為にも適用されます。もちろん、データを取得してから、控除アクションをディスパッチする方法は複数ありますが、コンポーネントを1つにまとめておくことは、コンポーネントに関係しない単一の場所で行うことが常にベスト・アイデアです。これにより、今後、アプリケーションをよりスケーラブルにすることができます。コンポーネントは常に可能な限りシンプルでなければならず、データを提示したり、入力を取り、バックグラウンドロジックを持たないようにしてください。あなたはredux-sagaについて読むこともできます。ジェネレータを使用してreduxのより高度な使用法。 – mkatanski

+0

ところで、私の答えが正しいと分かったら、それを受け入れたものとしてマークしてください:) – mkatanski

関連する問題