1

我对 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 };

我使用以下方式从我的 React 组件调度此操作mapDispatchToProps

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
4

2 回答 2

3

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

让我先回答你问题的这一部分。如第一个答案中所述,您需要Redux Thunk,一个中间件,用于dispatch您的动作创建者。

默认情况下,Redux 操作创建者返回普通对象,如下所示:

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

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

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

在 Redux Thunk 的特定情况下,您返回该dispatch函数。Redux Thunk 使您能够dispatch通过将其作为参数提供给您的操作创建者来返回。

但我得到了action:undefined

让我们打开这个包装。我们知道——感谢 Redux Thunk——你可以使用dispatch. 但是,正如您在编辑的问题中提到的,您仍然会收到“普通对象”错误。

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

这是因为您dispatch使用 Promise 对象而不是普通对象调用。

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()));
    };
};

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

const visitLocationAction = (characterId, location) => {
    return (dispatch) => {
        return dispatch(visitLocation(characterId, location))
            .then(() => dispatch({
                type: 'VISIT_LOCATION_SECOND_TIME'
                payload: fetchSomething()
            }));
    };
};
于 2018-08-24T16:03:09.630 回答
1

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

所以你可以这样写你的动作:

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))
      }
    }

然后像你提到的那样使用它:

const mapDispatchToProps = dispatch => (
  bindActionCreators({ firstAction }, dispatch)
);
于 2018-08-23T15:05:29.123 回答