【发布时间】:2017-12-01 00:48:02
【问题描述】:
这是我还没有找到标准解决方案的一件事。
我使用 redux-saga 设置了我的商店以进行副作用处理,我从组件调度了一个动作(具有异步副作用),现在希望组件在处理完副作用后执行某些操作(例如导航到另一条路线/屏幕,弹出模式/吐司或其他任何东西)。
我还想在失败时显示加载指示器或任何错误。
在 redux 之前,这种流程是直截了当的,看起来像这样:
try {
this.setState({loading: true});
const result = await doSomeRequest();
this.setState({item: result, loading: false});
} catch (e) {
this.setState({loading: false, error: e});
}
使用 redux,我通常希望调度一个启动流程的操作并将所有相关信息保存在存储中,以允许许多组件监听正在发生的事情。
我可以有 3 个动作,“请求”、“成功”、“失败”。 在我的组件中,我将分派请求的操作。 然后,负责的 saga 将在处理“请求”时调度“成功”或“失败”操作。
我的组件将反映所做的更改。 但是我还没有找到一个标准的方法来确定动作是否已经完成。也许由于异步操作(NO-OP,但我猜加载状态仍然会改变),商店没有更新。但是操作仍然成功,我想做一些事情,比如导航到另一个屏幕。
我真的尝试在 redux 文档、redux-saga 文档或 Stackoverflow/Google 中找到这种(看似常见的)场景,但没有成功。
注意:同样使用 redux-thunk,我认为这种行为很容易实现,因为我可以 .then 在异步操作调度上,并会在 catch 中接收成功操作或错误操作(如果我是,请纠正我错了,从来没有真正使用过thunk)。但是我还没有看到使用 redux-saga 实现相同的行为。
我提出了 3 个具体的解决方案:
最原始的解决方案,仅处理来自组件的“成功”/“失败”操作。现在这个解决方案我不是很喜欢。在我的具体实现中,没有任何动作表明异步请求已启动。副作用直接在组件中处理,而不是在 saga 中抽象出来。大量潜在的代码重复。
在调度请求操作之前运行一次性 saga,使“成功”/“失败”操作相互竞争,并允许对第一个发生的操作做出反应。为此,我编写了一个帮助程序将 saga 的运行抽象化:https://github.com/milanju/redux-post-handling-example/blob/master/src/watchNext.js 这个例子我更喜欢 1. 因为它简单且具有声明性。虽然我不知道在运行时创建这样的 saga 是否会产生负面影响,或者也许还有另一种“正确”的方式来实现我正在使用 redux-saga 做的事情?
-
将与操作相关的所有内容(加载、成功标志、错误)放入存储中,并在 componentWillReceiveProps 中对操作更改做出反应((!this.props.success && nextProps.success))意味着操作已成功完成)。 这类似于第二个示例,但适用于您选择的任何副作用处理解决方案。 也许我正在监督一些事情,比如检测一个动作是否成功,如果道具很快出现并且进入 componentWillReceiveProps 的道具将“堆积”并且组件完全跳过从不成功到成功的过渡?
请随意查看我为这个问题创建的示例项目,其中已实施完整的示例解决方案:https://github.com/milanju/redux-post-handling-example
我希望就我用来处理所描述的动作流的方法提供一些意见。
- 我在这里误解了什么吗?我想出的“解决方案”对我来说根本不是直截了当的。也许我从错误的角度看待问题。
- 上面的例子有什么问题吗?
- 是否有针对此问题的最佳实践或标准解决方案?
- 您如何处理所描述的流程?
感谢阅读。
【问题讨论】:
-
这里有同样的问题。我很惊讶这不是图书馆已经处理的事情,因为这感觉很基础。
标签: reactjs asynchronous redux react-redux redux-saga