我正在学习Redux,并且在更新另一个分支(分支B)之前遇到了与确保我的状态树的分支(分支A)已完成更新有关的问题。分支B依赖于分配给分支A中新更新项目的ID,因此我希望分支B的更新功能在更新分支A的分派功能完成后进行分派。我有多个与各个分支对应的reducer,我使用combineReducers来组合它们。
我使用以下命令从组件中分派更新分支A的操作:
/* update Branch A */
this.props.dispatch(actions.addCriterion(this.state));
按顺序调度在下一行代码上更新分支B的操作会导致分支B看不到分支A分派导致的更新状态信息。
/* update Branch B */
this.props.dispatch(actions.completeScoreGrid(this.props.alternatives, this.props.criteria));
但是,如果我使用setTimeout并在调用A之后等待一段时间后,一切都按预期工作。在这种情况下,状态更新完成,B看到它应该的一切
/* update Branch B after a 1 second pause */
var that = this;
setTimeout(function() {
that.props.dispatch(actions.completeScoreGrid(that.props.alternatives,
that.props.criteria));
}, 1000);
但是,我确定使用设置超时不是正确的方法。我看起来像redux-thunk,redux-promise,redux-promise-middleware和redux-saga,我不确定哪个是适合这个问题的工具,或者它们中的任何一个是否是正确的工具。解决这类问题的正确方法是什么?
答案 0 :(得分:1)
这里的问题是,您从中发送这些操作的组件中的criteria
prop没有机会更新。但是,state atom本身内部的条件值已经更新。请允许我进一步解释。
让我们调用这行代码Line 1
:
this.props.dispatch(actions.addCriterion(this.state));
让我们调用这行代码Line 2
:
this.props.dispatch(actions.completeScoreGrid(this.props.alternatives, this.props.criteria));
Line 1
完成后,redux state atom中的criteria
包含新标准。但是,criteria
中的Line 2
道具尚未刷新,因为React尚未更新组件以响应redux状态更改。
那你怎么解决这个问题呢?有几种方法,但这是我最好的建议。您可以使用redux-thunk启用异步操作,并从异步操作创建器中的redux state atom获取条件,而不是将this.props.criteria
传递给completeScoreGrid
动作创建者。假设条件存储在state.criteria
。
function completeScoreGrid(alternatives) {
return (dispatch, getState) => {
const state = getState();
const criteria = state.criteria;
dispatch({
type: 'COMPLETE_SCORE_GRID',
payload: {
criteria,
alternatives
}
});
}
}
然后,您可以更新分支B以响应此操作。如果您有任何问题,请告诉我。
答案 1 :(得分:0)
我最终使用thunk-redux来解决问题,并将Brandon Lewis的帖子标记为上面的答案。
此外,Reddit用户cyex在我的Reddit帖子中发布了另一种技术,询问同样的问题。我测试了它,它也做了我想要完成的事情。我已经链接到下面的帖子,并在此粘贴了他的解决方案。
Link to Reddit post on this question
你能发布你的减速器的样子吗?新状态不会反映在第二次通话中听起来不对。 但是当你说分支B依赖于分配给分支A中的新项目的ID时...你是在reducer中还是在你的动作创建者中生成这个ID? 例如如果你的代码看起来像这样呢?
/* update Branch A */
var newCriterion = actions.addCriterion(this.state); // ID is assigned here, not in reducer
this.props.dispatch(newCriterion);
/* update Branch B */
var scoreGrid = actions.completeScoreGrid(this.props.alternatives, this.props.criteria, newCriterion.id);
this.props.dispatch(scoreGrid);
So the B reducer doesn't need to look at anything on another branch.