我似乎遇到了一种情况,我无法避免在Flux中发送调度问题。
我已经阅读了一些关于这个问题的类似问题,但除了setTimeout
黑客之外,似乎没有一个好的解决方案,我希望避免这些问题。
我实际上使用的是alt.js而不是Flux,但我认为概念是相同的。
想象一下最初呈现登录表单的组件。当用户登录时,会触发XHR,该XHR最终会使用身份验证信息(例如用户名)进行响应,然后根据身份验证信息获取一些安全数据并将其呈现而不是登录表单。
我遇到的问题是当我尝试触发基于XHR响应获取数据的操作时,它仍然在发送LOGIN_RESPONSE
动作,并触发可怕的
Error: Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
我创建了this jsfiddle来证明问题。
我有一个Wrapper
组件,根据用户是否在Contents
中设置,可以呈现登录按钮或MyStore
子组件。
Wrapper
组件中。LOGIN
操作。LOGIN_RESPONSE
行动将被调度(通过async mechanism in alt.js)。MyStore
更新用户名。Wrapper
组件会观察商店更改并更新其状态。Wrapper
呈现Content
组件,而不是登录按钮。Content
组件在mount上尝试调度FETCH_DATA
操作,该操作失败,因为调度程序仍在调度LOGIN_RESPONSE
。 (如果我将FETCH_DATA
调度包装在setTimeout
中,它可以正常运行,但感觉就像是黑客攻击了。这种情况的变化似乎是一种常见的情况。事实上,几乎所有相关问题都有类似的情况,但没有好的或具体的答案。
此数据流是否存在内在错误?做这样的事情的适当的Flux方式是什么?
答案 0 :(得分:1)
这是在许多库中componentDidMount
中调度的常见问题。解决方案是在React的批量更新中包装调度;幸运的是,Alt允许您使用batchingFunction
选项执行此操作:
var alt = new Alt({
// React.addons.batchedUpdates is deprecated:
// batchingFunction: React.addons.batchedUpdates
// use this instead in newer versions of React
// see https://discuss.reactjs.org/t/any-plan-for-reactdom-unstable-batchedupdates/1978
batchingFunction: ReactDOM.unstable_batchedUpdates
});
有关工作示例,请参阅https://jsfiddle.net/BinaryMuse/qftyfjgy/,有关不同框架中相同问题的说明,请参阅this Fluxxor issue。
答案 1 :(得分:0)
我相信我们忠诚的朋友Dispatcher有权投诉。
在我得出结论之前,我会试着描述一个假设的情况。假设一个应用程序有两个存储S1和S2以及两种操作A1和A2。通常的Flux实现的正确流程应该是这样的:
使用Flux优于传统MVC的最大优势之一是Flux为您提供可预测性的礼物。这种感觉赋予了开发人员以这样的方式使他们相信通过正确应用Flux理念,他们肯定执行的顺序总是有点类似于:
A1> S1> S2> A2> S1> S2> ...
这是一个非常好的交易,特别是在尝试查找错误来源时。有人可能会说,强制执行可预测的事件链可能会导致效率低下,而且他可能是正确的,特别是在处理异步呼叫时,但这是你为拥有如此大的权力所付出的代价!
由于异步调用,事情可能会变得有点混乱。可能会发生以下事件链:
A1> S1> A2> S2> S1> S2> ...
也许您的应用可以很好地处理这类事件链,但这种“不可预测性”会损害Flux单向数据流的基本动机。
我觉得社区对如何处理这种情况没有达成共识,但我会分享我的一般解决方案:“为了可预测性,请确保在最后一个完全处理之前不要触发任何新动作”。
这样做的一种方法是在触发任何其他操作之前,下载应用程序成功重新呈现的所有必要(新)数据。在您的示例中,这可以通过首先下载LOGIN_RESPONSE和FETCH_DATA操作中涉及的数据并将其包装在单个有效负载中然后调度它来实现,因此所有组件将具有他们已经在商店中想要的数据而无需更多