简体   繁体   English

如何使用Redux Promise Middleware链接操作?

[英]How do I chain actions with Redux Promise Middleware?

I am quite new to React and Redux. 我是React和Redux的新手。 I want to chain multiple API calls using redux-promise-middleware and implemented my actions as follows: 我想使用redux-promise-middleware链接多个API调用,并按如下方式实现我的操作:

locationActions.js: 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 };

I dispatch this action from my React component using mapDispatchToProps : 我使用mapDispatchToProps从我的React组件调度此操作:

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

This works! 这有效! However, I want to dispatch another action after visitLocation is settled and fulfilled. 但是,我希望在visitLocation结算和完成后发送另一个操作。 I can not call Promise.then() because it doesn't provide the dispatch method, therefore not "binding" my action to the reducer. 我无法调用Promise.then()因为它不提供dispatch方法,因此不会将我的操作“绑定”到reducer。

Tutorials mention I should call dispatch(secondAction()) but I do not have dispatch available in my action creators. 教程提到我应该调用dispatch(secondAction())但我的动作创建者没有可用的调度。

Can someone point out to me what am I missing? 有人能指出我错过了什么吗?

Edit: 编辑:

As suggested in the first answer, I tried the following approach: 正如第一个答案所示,我尝试了以下方法:

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

But I got action:undefined and the following error: 但我得到了行动:未定义和以下错误:

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

Tutorials mention I should call dispatch(secondAction()) but I do not have dispatch available in my action creators. 教程提到我应该调用dispatch(secondAction())但我的动作创建者没有可用的调度。

Let me answer this part of your question first. 让我先回答你问题的这一部分。 As mentioned in the first answer, you need Redux Thunk , a middleware, to use dispatch in your action creators. 正如第一个答案中提到的,您需要Redux Thunk (一种中间件)在您的动作创建者中使用dispatch

By default, Redux action creators return plain objects like this: 默认情况下,Redux操作创建者返回如下的普通对象:

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

With Redux Thunk, action creators can essentially return functions. 使用Redux Thunk,动作创建者基本上可以返回功能。 A function that returns a function is called a "thunk", hence the name of Redux Thunk. 返回函数的函数称为“thunk”,因此称为Redux Thunk。

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

In the specific case of Redux Thunk, you return the dispatch function. 在Redux Thunk的特定情况下,您将返回dispatch功能。 Redux Thunk enables you to return dispatch by providing it as a parameter to your action creators. Redux Thunk使您可以通过将其作为参数提供给您的操作创建者来返回dispatch

But I got action:undefined 但我action:undefinedaction:undefined

Let's unpack this. 我们打开这个。 We know--thanks to Redux Thunk--you can chain multiple actions together using dispatch . 我们知道 - 感谢Redux Thunk - 您可以使用dispatch多个动作链接在一起。 However, as you mentioned in your edited question, you still get the "plain object" error. 但是,正如您在编辑过的问题中提到的那样,仍然会出现“普通对象”错误。

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

This is because you called dispatch with a Promise object, not a plain object. 这是因为您使用Promise对象调用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()));
    };
};

To fix this problem, simply modify your second dispatch to use a plain object: 要解决此问题,只需修改第二个调度以使用普通对象:

const visitLocationAction = (characterId, location) => {
    return (dispatch) => {
        return dispatch(visitLocation(characterId, location))
            .then(() => dispatch({
                type: 'VISIT_LOCATION_SECOND_TIME'
                payload: fetchSomething()
            }));
    };
};

As mentioned in the documentation for redux-promise-middleware , The middleware can be combined with Redux Thunk to chain action creators. 正如redux-promise-middleware的文档中所提到的,中间件可以与Redux Thunk结合使用,以链接动作创建者。

So you can write your action like: 所以你可以写下你的行动:

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

or use async/await 或使用async / await

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

and then use it as you mentioned: 然后按照你的提及使用它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM