【问题标题】:Where to dispatch multiple actions in redux?在 redux 中在哪里调度多个操作?
【发布时间】:2017-11-03 10:29:15
【问题描述】:

我将 redux 与 connectredux-thunk 中间件和容器一起使用。

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

我知道从 reducer 中调度操作是一种反模式。

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

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

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

【问题讨论】:

  • 我相信this 描述了您正在寻找的确切模式。只需阅读该页面,您最感兴趣的部分可能是他们描述fetchPosts 函数的地方。
  • @saadq 感谢您的链接,它看起来像在动作创建者中......正确吗?
  • 请记住,dispatchSYNCHRONOUS 操作 :)

标签: javascript redux


【解决方案1】:

documentation 推荐的方法是在动作创建器中,如下所示:

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

然后您可能希望将动作创建者作为道具附加并使用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)

【讨论】:

【解决方案2】:

正如其他人指出的那样,The action creator 是调度多个操作的正确位置。

下面是action1 如何在您的action creator 中调度其他操作的示例。

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

【讨论】:

    【解决方案3】:

    虽然@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)
        ]))
    });
    

    【讨论】:

      【解决方案4】:

      动作创建者是调度多个动作的正确位置。虽然像下面这样的代码可以工作:

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

      【讨论】:

      • 感谢您的回答。我真的在寻找一种按顺序进行多次调度的方法。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        最简单的方法是使用专门的中间件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

        【讨论】:

          【解决方案7】:

          对于 2020 年的男士们... 动作应该在动作创建者中进行。对于那些想要调度一个动作并从 API 获取/发布一些数据的人可以使用这个想法。

          假设我们有一个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
              }));
            }
          }
          

          【讨论】:

            【解决方案8】:
            "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));
              }; 
            

            【讨论】:

              【解决方案9】:

              我不知道确切的用例,但由于 redux 使用异步逻辑,任何在事件循环的下一个滴答中运行第二次调度的解决方案都应该有效。

              store.dispatch({ type: 'ADD_TODO', text: 'Buy milk.' });
              
              setTimeout(() => {
                store.dispatch({ type: 'ADD_TODO', text: 'Take out garbage.' });
              }, 0);
              
              Promise.resolve(() => {
                store.dispatch({ type: 'ADD_TODO', text: 'Water plants.' });
              });
              

              如果第二个 dispatch 依赖于第一个 dispatch 的 actions,你可以从 store 中获取 state,检查它是否满足条件,然后 dispatch 第二个 action。最好保持操作的逻辑清晰和细化。

              因此,要回答这个问题,调度多个操作的正确位置是在第一个操作发起的点击处理程序内。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-06-30
                • 2017-04-14
                • 1970-01-01
                • 2017-11-09
                • 1970-01-01
                • 2018-01-24
                • 1970-01-01
                • 2019-12-29
                相关资源
                最近更新 更多