如何使用redux和redux-promise将多个axios调用合并到一个有效负载中?

时间:2016-12-13 20:32:07

标签: redux axios redux-promise

我正在尝试制作一个动作,它将进行两个单独的API调用,然后将数据合并在一起,然后传递给我的reducer。我尝试使用promise进行第一次调用,然后使用axios的transformResponse将数据合并到其中,但我不断收到未捕获错误:操作必须是普通对象。使用自定义中间件进行异步操作。错误。

最好的方法是什么?

1 个答案:

答案 0 :(得分:0)

重要的是,减速器始终是同步的。所以减速器不应该收到承诺。操作应仅包含普通数据,并采用以下形式:

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

redux-promise允许我们在一个动作的有效载荷中设置一个承诺。

一旦将redux-promise添加到中间件链中,我们就可以调度在其有效负载属性中具有承诺的操作。

redux-promise中间件将在到达商店之前处理此操作,并在承诺解决或拒绝后调度任何进一步的操作,并且有效负载将包含每种情况下的响应或错误。

一旦promise被解决或被拒绝,redux-promise分派的这些进一步的动作就像调度的任何动作一样是同步的。请记住,我们的中间件的工作是在动作有效负载中的承诺已解决或拒绝后发送 <。>

派遣行动 - &gt;中间件(redux-promise发送进一步的动作) - &gt;减速器从这些进一步的动作中获取错误或数据 - &gt;存储由reducers更新

这是一个自包含的示例,我们将向开放电影数据库api请求电影数据,以演示redux-promise的工作原理。

首先到商店

<强> 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函数作为参数传递给create store,然后将redux-promise作为applyMiddleware的参数提供。

现在是动作创建者。

当在下面调用动作创建者函数时,将发出axios请求。此请求将返回一个promise,然后通过我们的redux-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
     }
}

我们的减速机将获得我们承诺的结果。

主要功能处理在拒绝或解决承诺后由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;