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

Posted

技术标签:

【中文标题】如何使用 redux 和 redux-promise 将多个 axios 调用合并到一个有效负载中?【英文标题】:How can I merge multiple axios calls into one payload using redux and redux-promise? 【发布时间】:2017-04-29 01:01:18 【问题描述】:

我正在尝试进行一项操作,该操作将进行两次单独的 API 调用,然后将数据合并在一起,然后传递给我的减速器。我尝试使用 promise 进行第一次调用,然后使用 axios 的 transformResponse 将数据合并到其中,但我不断收到 Uncaught Error: Actions must be plain objects。使用自定义中间件进行异步操作。错误。

最好的方法是什么?

【问题讨论】:

欢迎来到 Stack Overflow!您可以先使用tour,然后学习How to Ask 一个好问题并创建一个minimal reproducible example。这让我们更容易为您提供帮助。 【参考方案1】:

重要的是,reducer 总是同步的。因此,reducer 不应该收到承诺。操作应仅包含纯数据并采用以下形式:


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

redux-promise 允许我们在动作的负载中加入一个承诺。

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

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

一旦 promise 被解决或拒绝,redux-promise 调度的这些进一步的动作是同步的,就像调度的任何动作一样。请记住,我们中间件的工作是动作负载中的承诺已解决或被拒绝之后调度其他动作。

调度动作 --> 中间件(redux-promise 调度进一步的动作) --> 减速器从这些进一步的动作中获取错误或数据 --> 存储由减速器更新

这是一个独立的示例,我们将向开放的电影数据库 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 函数作为参数传递给创建 store,然后将 redux-promise 作为参数提供给 applyMiddleware。

现在是动作创建者。

当在下面调用 action creator 函数时,将发出 axios 请求。这个请求会返回一个 promise,然后通过我们的 redux-promise 中间件传递。

actions/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
     

然后我们的 reducer 将得到我们承诺的结果。

主函数处理在 promise 被拒绝或解决后由 redux-promise 中间件调度的操作

reducers/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;

【讨论】:

以上是关于如何使用 redux 和 redux-promise 将多个 axios 调用合并到一个有效负载中?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 redux 工具包动态生成 reducer 和 action 类型?

如何使用 React-Bootstrap 和 Redux 显示/隐藏 Modal?

如何导出 mapStateToProps 和 Redux 表单?

如何使用 redux-thunk 和 TypeScript 调度 ThunkAction

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

thunk 和 action 完成后如何使用 redux 的当前状态?