在redux中发送多个动作的位置?

时间:2017-06-02 05:49:34

标签: javascript redux

我正在使用带有connectredux-thunk中间件和容器的redux。

目前,当用户执行某个操作时,例如,单击一个按钮,我需要调度该操作(同步),该操作将调度其他几个操作(异步)。

我知道在reducer中调度动作是一种反模式。

我想知道这个代码的合适位置。

目前我不确定它是否应该留在:

  • 动作创作者。
  • 在使用store.subscribe。
  • 的容器中

8 个答案:

答案 0 :(得分:14)

根据documentation推荐的方式是在动作创建者中,如下所示:

function actionCreator(payload) {
    return dispatch => {
        dispatch(action1(payload))
        dispatch(action2(payload))
    }
}

然后,您可能希望将动作创建者附加为prop,并使用mapDispatchToProps将其传递给容器,如上面提到的示例here中所示。所以它看起来像这样:

const mapDispatchToProps = dispatch => ({
   action1: some_payload => dispatch(action1(some_payload))
   action2: some_payload => dispatch(action2(some_payload))
})

// your component
export default connect(mapStateToProps, mapDispatchToProps)(YourApp)

答案 1 :(得分:14)

正如其他指出的The action creator是调度多项行动的正确位置。

下面举例说明action1如何在action creator中发送其他操作。

const action1 = id => {
  return dispatch => {
    dispatch(action2(id))
    dispatch(action3(id))
  }
}

答案 2 :(得分:2)

@GibboK的解决方案对我不起作用:

const mapDispatchToProps = (dispatch) => ({
  action2: id => dispatch(Actions.action2(id)),
  action3: id => dispatch(Actions.action3(id)),
  action1: (dateId, attrId) => {
    return dispatch => {
      dispatch(Actions.action2(dateId));
      dispatch(Actions.action3(attrId));
    }
  }
});

我最终选择了redux-batched-actions。像魅力一样工作:

const mapDispatchToProps = (dispatch) => ({
  action2: id => dispatch(Actions.action2(id)),
  action3: id => dispatch(Actions.action3(id)),
  action1: (dateId, attrId) =>
    dispatch(batchActions([
      Actions.action2(dateId),
      Actions.action3(attrId)
    ]))
});

答案 3 :(得分:2)

动作创建者是分派多个动作的正确位置。尽管类似以下代码的代码可以工作:

function actionCreator(payload) {
    return dispatch => {
        dispatch(action1(payload))
        dispatch(action2(payload))
    }
}

我强烈建议基于redux-thunk的操作创建者始终返回已解决的Promise,以便此类操作创建者可以成为另一个异步调用的一部分。因此,对上述内容的最简单更新是:

function actionCreator(payload) {
    return dispatch => {
        dispatch(action1(payload));
        dispatch(action2(payload));
        return Promise.resolve();
    }
}

然后可以使用以下命令派发至以上: actionCreator(payload).then(doAnotherAction(anotherPayload)) 或以下,如果我们需要保持通话顺序: actionCreator(payload).then(() => doAnotherAction(anotherPayload))

如果您希望对动作创建者进行“永不过时”的处理,以便它可以处理异步和同步动作创建者的调用,则可以将其编写为:

function actionCreator(payload) {
    return dispatch =>
        Promise.resolve(dispatch(action1(payload))).then(
        () => dispatch(action2(payload)));
}

而且,如果您喜欢ES6箭头符号,则可以将以上定义为:

const actionCreator = payload => dispatch =>
        Promise.resolve(dispatch(action1(payload))).then(
        () => dispatch(action2(payload)));

答案 4 :(得分:1)

如果您有Promise Middleware,则可以使用以下语法,以便可以在.then()上使用dispatch(topLevelAction())

export const topLevelAction = () => dispatch => {
    return Promise.all([dispatch(action1()), dispatch(action2()), dispatch(action3())])
}

答案 5 :(得分:0)

对于2020年的球员... 这些动作应该在动作创建器中进行。对于那些希望分派动作并从API中获取/发布一些数据的人可以使用此Idea。

让我们假设我们有一个actions.js文件,并且希望在获取数据之前分派加载操作。

function requestPosts() {
    return {
      type: "loading"
    }
  }

这是获取动作功能

function fetchPosts() {
 return dispatch => {
    // dispatch the loading
    dispatch(requestPosts());
    // fetch data from api
  return fetch("https://www.yoururl.com/api")
   .then(response => response.json())
   .then(json => dispatch({
       type: "fetching successful",
       payload: json
    }));
  }
}

答案 6 :(得分:0)

"had similar issue. had to create a function 
that accepts object with  the actions you want to 
dispatch to the store and individual params for 
respective action"

dispatchMultiple({params: {
    params1: "<arg for first action>" ,
    params2: "<arg for second action>",
                        },

})
const dispatchMultiple = (obj) => {
    dispatch(obj.actions.action1(obj.params.params1));
    dispatch(obj.actions.action2(obj.params.params2));
  }; 

答案 7 :(得分:-2)

最简单的方法是使用专用的中间件redux-soldier

import { createStore, applyMiddleware } from 'redux'
import { reduxSoldierMiddleware } from 'redux-soldier'

const store = createStore(rootReducer, applyMiddleware(reduxSoldierMiddleware))
store.dispatch([
  {type: 'INCREMENT'}, // traditional action
  addTodo('Start using redux-soldier'), // action creator
  fetchUser(), // thunk action
])

redux-soldier也是redux-thunk

的完整替代品

有关更多信息,请查看文档redux-soldier