乐闻世界logo
搜索文章和话题

Redux 如何同时 dispatch 多个 actions ?

7 个月前提问
3 个月前修改
浏览次数117

6个答案

1
2
3
4
5
6

当您想要同时分发多个 actions 时,Redux 本身并不提供直接的方法来同时分发它们,因为每个 dispatch 调用通常只处理一个 action。但是,有几种模式可以实现相似的效果:

1. 连续 Dispatch

最简单的方法就是连续调用几次 dispatch,每个调用分发一个 action。

javascript
dispatch(actionCreator1()); dispatch(actionCreator2()); dispatch(actionCreator3());

这种方法的缺点是它可能会导致多次重新渲染,如果每个 action 都会改变 Redux 状态的话。

2. 批量 Dispatch(中间件)

您可以使用中间件来扩展 Redux 的功能,比如 redux-batch,它允许您将多个 actions 打包成单个批量 action,然后由中间件展开并逐一分发。

javascript
import { batchDispatchMiddleware } from 'redux-batch'; // 应用中间件 const store = createStore( reducer, applyMiddleware(batchDispatchMiddleware) ); // 分发批量 actions store.dispatch(batchActions([actionCreator1(), actionCreator2(), actionCreator3()]));

这种方法可以减少不必要的重新渲染,因为状态更新是在所有 actions 都被处理后才发生的。

3. Promise 中 Dispatch

如果您的 actions 是异步的,您可以在一个 Promise 中链式调用它们,使用 Promise.all 或者 async/await。但是这只适用于异步 actions,并且它们仍然是逐个处理的,并不是真正的同时。

javascript
Promise.all([ dispatch(asyncActionCreator1()), dispatch(asyncActionCreator2()), dispatch(asyncActionCreator3()), ]);

或者使用 async/await

javascript
async function dispatchMultipleActions() { await dispatch(asyncActionCreator1()); await dispatch(asyncActionCreator2()); await dispatch(asyncActionCreator3()); }

4. 自定义 Action Creators

您可以创建一个 action creator,它返回一个函数(thunk)而不是一个 action 对象。这个函数可以分发多个 actions。

javascript
const compositeAction = () => (dispatch, getState) => { dispatch(actionCreator1()); dispatch(actionCreator2()); dispatch(actionCreator3()); }; // 然后使用 dispatch(compositeAction());

这种方法通常是与 redux-thunk 中间件一起使用的。


在实际应用中,连续分发是最简单和最直接的方法,但如果你想要避免多次渲染,则批量分发或者封装 actions 的方法会比较有效。重要的是要评估你的应用性能需求和状态更新的复杂性,选择最适合你情况的方案。

2024年6月29日 12:07 回复

根据文档推荐的方法是在操作创建者中,如下所示:

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

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

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

2024年6月29日 12:07 回复

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

下面的示例action1说明了如何在您的action creator.

shell
const action1 = id => { return dispatch => { dispatch(action2(id)) dispatch(action3(id)) } }
2024年6月29日 12:07 回复

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

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

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

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

actionCreator(payload).then(doAnotherAction(anotherPayload)) 如果我们需要维护调用顺序, 则可以使用以下内容分派到上面: 或以下内容:actionCreator(payload).then(() => doAnotherAction(anotherPayload))

如果您希望您的动作创建器“面向未来”,以便它可以处理调用异步和同步动作创建器,您可以将其编写为:

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

而且,如果你喜欢 ES6 箭头表示法,上面的可以定义为:

shell
const actionCreator = payload => dispatch => Promise.resolve(dispatch(action1(payload))).then( () => dispatch(action2(payload)));
2024年6月29日 12:07 回复

如果您有Promise Middleware,您可以使用此语法,这样您就可以.then()在您的dispatch(topLevelAction())

shell
export const topLevelAction = () => dispatch => { return Promise.all([dispatch(action1()), dispatch(action2()), dispatch(action3())]) }
2024年6月29日 12:07 回复

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

shell
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。像魅力一样工作:

shell
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) ])) });
2024年6月29日 12:07 回复

你的答案