如何与Redux Promise中间件链接动作?

时间:2018-08-23 13:57:11

标签: javascript reactjs redux redux-promise-middleware

我对React和Redux很陌生。我想使用redux-promise-middleware链接多个API调用,并执行以下操作:

locationActions.js:

import { visitLocation } from '../services/actionService';

export const VISIT_LOCATION = 'VISIT_LOCATION';
export const VISIT_LOCATION_PENDING = 'VISIT_LOCATION_PENDING';
export const VISIT_LOCATION_FULFILLED = 'VISIT_LOCATION_FULFILLED';
export const VISIT_LOCATION_REJECTED = 'VISIT_LOCATION_REJECTED';

const visitLocationAction = (characterId, location) => ({
    type: VISIT_LOCATION,
    // visitLocation returns a new promise
    payload: visitLocation(characterId, location)
});

export { visitLocationAction as visitLocation };

我使用mapDispatchToProps从我的React组件中调度此动作:

const mapDispatchToProps = dispatch => (
    bindActionCreators({ visitLocation }, dispatch)
);

这有效!但是,我想在visitLocation解决并完成后再调度其他操作。我无法调用Promise.then(),因为它不提供dispatch方法,因此不能将我的操作“绑定”到减速器。

教程提到我应该打电话给dispatch(secondAction()),但我的动作创建者中没有可用的调度。

有人可以向我指出我在想什么吗?

编辑:

根据第一个答案的建议,我尝试了以下方法:

import { visitLocation } from '../services/locationService';
import { fetchSomething } from '../services/otherService';

const visitLocationAction = (characterId, location) => {
    return (dispatch) => {
        return dispatch(visitLocation(characterId, location))
            .then(() => dispatch(fetchSomething()));
    };
};

export { visitLocationAction as visitLocation };

但是我得到了action:undefined和以下错误:

Error: Actions must be plain objects. Use custom middleware for async actions.
    at dispatch (redux.js:200)
    at redux-logger.js:1

2 个答案:

答案 0 :(得分:3)

  

教程提到我应该打电话给 Shell App.Path & "\winhlp32.exe myhelpfile" ,但我的动作创建者中没有可用的调度。

首先让我回答您问题的这一部分。如第一个答案所述,您需要Redux Thunk(一种中间件)才能在动作创建者中使用dispatch(secondAction())

默认情况下,Redux动作创建者返回的普通对象如下:

dispatch

使用Redux Thunk,动作创建者实际上可以返回函数。返回函数的函数称为“ thunk”,因此称为Redux Thunk。

const returnsAnObject = () => ({
  type: 'MY_ACTION'
  payload: ...,
  meta: ....
})

在Redux Thunk的特定情况下,您返回const returnsAFunction = (dispatch) => dispatch({ type: 'MY_ACTION' payload: ..., meta: .... }) 函数。 Redux Thunk使您可以通过将dispatch作为参数提供给动作创建者来返回。

  

但是我得到了dispatch

让我们打开包装。我们知道-由于Redux Thunk,您可以使用action:undefined将多个动作链接在一起。但是,正如您在已编辑问题中提到的那样,您仍然会收到“普通对象”错误。

dispatch

这是因为您通过Promise对象而不是普通对象调用了Error: Actions must be plain objects. Use custom middleware for async actions. at dispatch (redux.js:200) at redux-logger.js:1

dispatch

要解决此问题,只需修改第二个调度以使用普通对象即可:

const visitLocationAction = (characterId, location) => {
    return (dispatch) => {
        return dispatch(visitLocation(characterId, location))

            // Yes, it is correct to call dispatch here
            // However, `dispatch` accepts plain objects, not Promise objects
            .then(() => dispatch(fetchSomething()));
    };
};

答案 1 :(得分:0)

redux-promise-middleware的文档中所述,中间件可以与Redux Thunk结合使用以链接动作创建者。

因此,您可以将操作写为:

e

或使用异步/等待

const secondAction = (data) => ({
  type: 'SECOND',
  payload: {...},
})

const thirdAction = (data) => ({
  type: 'THIRD',
  payload: {...},
})

const firstAction = () => {
  return (dispatch) => {
    return visitLocation(characterId, location)
      .then((data) => dispatch(secondAction(data)))
      .then((data) => dispatch(thirdAction(data)))
  }
}

然后按照您提到的方式使用它:

const secondAction = (data) => ({
      type: 'SECOND',
      payload: {...},
    })

    const thirdAction = (data) => ({
      type: 'THIRD',
      payload: {...},
    })

    const firstAction = async () => {
      return (dispatch) => {
        const data = await visitLocation(characterId, location));
        dispatch(secondAction(data))
        dispatch(thirdAction(data))
      }
    }