我正在使用带有connect
和redux-thunk
中间件和容器的redux。
目前,当用户执行某个操作时,例如,单击一个按钮,我需要调度该操作(同步),该操作将调度其他几个操作(异步)。
我知道在reducer中调度动作是一种反模式。
我想知道这个代码的合适位置。
目前我不确定它是否应该留在:
答案 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。