0

2 つの個別の API 呼び出しを行い、データをマージしてレデューサーに渡す 1 つのアクションを作成しようとしています。Promise を使用して最初の呼び出しを行い、次に axios の transformResponse を使用してデータをマージしようとしましたが、Uncaught Error: Actions must be plain objects が発生し続けます。非同期アクションにはカスタム ミドルウェアを使用します。エラー。

これを行う最善の方法は何ですか?

4

1 に答える 1

0

重要なことに、レデューサーは常に同期しています。したがって、Reducer は promise を受け取るべきではありません。アクションはプレーン データのみで構成され、次の形式を取る必要があります。

{
  type: 'ADD_TODO',
  payload: {
    text: 'Do something.'  
  }
}

redux-promise を使用すると、アクションのペイロードに promise を入れることができます。

redux-promise がミドルウェア チェーンに追加されると、ペイロード プロパティに promise を持つアクションをディスパッチできます。

redux-promise ミドルウェアは、ストアに到達する前にこのアクションを処理し、Promise が解決または拒否されると、それ以上のアクションをディスパッチします。ペイロードは、それぞれの場合の応答またはエラーで構成されます。

promise が解決または拒否された後に redux-promise によってディスパッチされるこれらの追加のアクションは、ディスパッチされるアクションと同様に同期的です。ミドルウェアの仕事は、アクション ペイロードの promise が解決または拒否された後に、追加のアクションをディスパッチすることであることを思い出してください。

ディスパッチ アクション --> ミドルウェア (redux-promise はさらにアクションをディスパッチします) --> レデューサーはこれらの追加アクションからエラーまたはデータを取得します --> レデューサーによって更新されたストア

これは、redux-promise がどのように機能するかを示すために、オープン ムービー データベース API にムービーのデータをリクエストする自己完結型の例です。

まずはお店へ

store.js

import { createStore, combineReducers, applyMiddleware } from 'redux'
import promiseMiddleware from 'redux-promise'

let rootReducer = combineReducers(reducers)

let store = createStore(
  rootReducer,
  applyMiddleware(promiseMiddleware)
)

次に、ストアを作成するための引数として Redux の applyMiddleware 関数を渡し、applyMiddleware の引数として redux-promise を提供する必要があります。

現在はアクションクリエーター。

以下でアクションクリエーター関数が呼び出されると、axios リクエストが行われます。このリクエストは、redux-promise ミドルウェアを介して渡される promise を返します。

アクション/index.js

export function requestMovie(movieTitle) { 
    // create the url for our api request
    const url = `http://www.omdbapi.com/??=${movieTitle}&y=&plot=short&r=json`

    return { // return our action
        type: 'REQUEST_MOVIE',
        payload: axios.get(url)  // this .get method returns a promise
     }
}

レデューサーには、Promise の結果が与えられます。

main 関数は、promise が拒否または解決された後に redux-promise ミドルウェアによってディスパッチされるアクションを処理します。

レデューサー/index.js

import { combineReducers } from 'redux';

const rootReducer = combineReducers({
    movies: movies,
    err: err
});

function err(err = false, action){
    switch (action.type) {
       case 'REQUEST_MOVIE':
        return(action.payload.response.status !== 200)
    }

    return err;
}

function movies(movies = [], action){
    switch (action.type) {
        case 'REQUEST_MOVIE':
          //  if promise was not rejected the data property on our action payload will exist comprising the movie data that we requested
          if(action.payload.response.status === 200){
             return [...movies, action.payload.response.data]
            } else{
                return [movies]
            }
    }

    return movies
}

export default rootReducer;
于 2016-12-13T22:27:20.760 に答える