【问题标题】:How to avoid action chains如何避免动作链
【发布时间】:2015-06-01 06:49:59
【问题描述】:

我正在尝试理解 Flux 模式。

我相信,在任何好的设计中,应用程序都应该由相对独立且通用(因此可重用)的组件组成,这些组件通过特定的应用程序逻辑粘合在一起。

在 Flux 中有特定领域的 Store 封装数据和领域逻辑。这些可能会在同一域的另一个应用程序中重用。

我认为还应该有特定于应用程序的商店来保存应用程序状态和逻辑。这是胶水。

现在,我尝试将其应用于虚构的“GPS Tracker”应用:

...

当用户点击[Stop Tracking]按钮​​时,对应的ViewController会引发STOP_CLICK

  • AppState.on(STOP_CLICK):

    • dispatch(STOP_GEOLOCATION)
    • dispatch(STOP_TRACKING)
  • GeolocationService.on(STOP_GEOLOCATION):

    • stopGPS(); this.on = false; emit('change')
  • TrackStore.on(STOP_TRACKING):

    • saveTrack(); calcStatistics(); this.tracking = false; emit('change')
    • dispatch(START_UPLOAD)

所以,我有一个事件滚雪球。

据说在 Flux 中一个 Action 不应该引发另一个 Action。 但我不明白这是怎么做到的。

我认为用户操作不能直接转到域商店,因为这些应该与 UI 无关。 相反,AppState(或应用逻辑所在的任何位置)应该将用户操作转换为域操作。

  1. 如何重新设计这种 Flux 方式?
  2. 应用程序逻辑应该去哪里?
  3. 尝试保持域存储独立于应用程序逻辑是否正确?
  4. “服务”的地方在哪里?

谢谢。

【问题讨论】:

    标签: reactjs-flux flux


    【解决方案1】:

    所有应用程序逻辑都应该存在于存储中。他们决定应该如何响应特定操作(如果有的话)。

    商店没有二传手。进入 store 的唯一方法是通过 dispatch 的 action,通过 store 向 dispatcher 注册的回调。

    动作不是设置器。尽量不要这样想。操作应该只是报告现实世界中发生的事情用户以某种方式与 UI 交互,服务器以某种方式响应某种方式等。

    这在我看来很像二传手的想法:

    调度(STOP_GEOLOCATION)

    调度(STOP_TRACKING)

    相反,调度实际发生的事情:STOP_TRACKING_BUTTON_CLICKED(或 TRACKING_STOPPED,如果您想与 UI 无关)。然后让商店弄清楚该怎么做。所有商店都将收到该操作,并且如果需要,他们都可以对其做出响应。您响应两个不同操作的代码应该响应同一个操作。

    通常,当我们发现我们想要在一个调度中调度时,我们只需要备份到发生的原始事情并让整个应用程序对此做出响应。

    【讨论】:

    • 看起来我希望“让 AppStore 协调特定领域的商店”与 Flux 不兼容。你的答案是让特定领域的商店直接对 UI 操作做出反应(从而使它们也特定于应用程序),而不是追求神话般的独立性和可重用性?谢谢
    • TRACKING_STOPPED 没有任何特定于应用程序的内容。但是,它有一些特定于跟踪的东西。因此,如果您希望 GeolocationStore 能够对此做出响应,您确实需要编写代码来做到这一点。幸运的是,调度员已经将所有动作发送到所有商店,所以你已经完成了一半。现在假设,在您编写完该代码后,您想将 GeolocationStore 移动到不使用跟踪的应用程序中。您是否会在 GeolocationStore 中有一些您没有使用的额外内容?是的。但这并不意味着它依赖于 UI 或其他不可重用。
    • 还是不清楚。因此,当用户单击按钮时,某些 ViewController 会触发 TRACKING_STOPPED 并且 Store 会自行更新。现在,我需要向用户显示一个确认对话框。因此,我将触发的操作更改为 TRACKING_STOP_REQUEST 和 AppStore 更改,以便显示确认将或不会上升 TRACKING_STOPPED。到目前为止,一切都很好。现在,我向 AppStore 添加了一些逻辑来确定我们是否需要确认:if (needConfirmation) this.state.showStopConfirmation = true else fire(TRACKING_STOPPED) 所以,我有一个动作链。如何正确处理?谢谢。
    • 商店不会触发操作。动作可能只由外部世界的一些变化引起:用户点击、服务器响应、浏览器启动新的动画帧等。所以这里的问题是您将动作视为设置器。把它们想象成报纸,报道外界的新闻。请注意您的所有示例如何对操作使用命令式名称。我在这里的建议都是过去式:它们已经发生了;行动只是一份报告。
    • 因此,如果您需要停止跟踪以响应 StoreB 中的 TRACKING_STOP_REQUESTED,仅当 StoreA 表示您应该这样做时,您将响应两个商店中的操作。在 StoreB 中,您将 waitFor(StoreA.getDispatchToken()) 然后调用 StoreA.getFoo() 以确定是否应该停止跟踪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多