ClojureScript 重构订阅解引用困境

ClojureScript Re-frame subscription dereferencing dilemma

以下方法中最好的是什么?

外部订阅,提前取消引用

(defn component [msg]
    [:p msg]))

(let [msg (rf/subscribe [:msg])]
    [component @msg]

外部订阅,延迟取消引用

(defn component [msg]
    [:p @msg]))

(let [msg (rf/subscribe [:msg])]
    [component msg]

内部订阅,提前取消引用

(defn component []
   (let [msg @(rf/subscribe [:msg])]
      [:p msg])))

内部订阅,延迟取消引用

(defn component []
   (let [msg (rf/subscribe [:msg])]
      [:p @msg])))

当我使用外部订阅保持内部组件纯净时,我可能会得到许多参数,这些参数需要通过通常不相关的父级的深层嵌套结构传递。那很容易变得一团糟。

当我订阅内部组件时,它变得不纯,失去了易测试性。

此外,我想知道早期和晚期取消引用之间是否存在重要区别,除了我在测试后者时必须通过 reagent/atom

不知道这是否解决了您的难题,但自从 Re-frame 0.9 以来,您可以在需要订阅值的任何地方编写 @(rf/subscribe [:msg])。订阅已缓存,因此使用相同路径创建多个订阅不会产生多个订阅。 此博客文章中的更多信息:https://lambdaisland.com/blog/11-02-2017-re-frame-form-1-subscriptions and this Re-frame issue.

一如既往,我们的答案是 "it depends",但是......

外部订阅,早期 deref 导致 pure/testable 内部订阅。因此,当这对您很重要时,这可能是一个不错的选择。不过这种风格我们用的不多

外部订阅,延迟取消引用 我们已经积极地摆脱了这种风格,因为它产生了我们后来发现难以理解的代码。顺便说一句,如果我们确实传递了 ratoms/cursors/subscriptions,我们喜欢在参数名称上放置一个尾随的 * 以明确它们是一个引用,而不是一个值。

内部订阅,早期deref可能是最常用的,我猜。一段时间后感觉很自然。也许使用 <sub from LIN

内部订阅,后期取消引用这也行,但我更喜欢直接在上面的变体。总是担心您可能会忘记在使用时添加 @,这可能是一个令人讨厌的错误。