【问题标题】:How to update Reagent vector in an atom如何更新原子中的试剂向量
【发布时间】:2017-09-28 10:37:26
【问题描述】:

我有一个试剂原子:

(defonce order (r/atom {:firstName "" :lastName "" :toppings [] }))

我想向:toppings 向量添加浇头。我尝试了很多变化:

(swap! (:toppings order) conj "Pepperoni") 这给了我:Uncaught Error: No protocol method ISwap.-swap! defined for type null:

(swap! order :toppings "Pepperoni") 有点工作,但只是更新顺序,而不是 :toppings 向量。当我 deref order 时,我只得到最新的值。

向我的:toppings 向量添加(和删除)值的正确方法是什么?

【问题讨论】:

  • 以下所有答案都很有价值。我接受了最直接回答问题的答案,但其他人更深入地了解了如何使用原子。

标签: clojure clojurescript reagent


【解决方案1】:

再解释一下,当您执行(swap! (:toppings order) ...) 时,您正在从order 检索:toppings 键,如果它是一个映射,这将是有意义的,但它是一个原子,所以(:toppings order) 返回nil.

swap! 的第一个参数应该始终是一个原子(Reagent 原子的工作方式相同)。第二个参数应该是一个以原子内容作为第一个参数的函数。然后,您可以选择提供更多将传递给函数参数的参数。

您可以执行以下操作,而不是 minhtuannguyen 的回答:

(swap! order
  (fn a [m]
    (update m :toppings
      (fn b [t]
        (conj t "Pepperoni")))))

fn a 接收到 atom 内部的 map,将其绑定到 m,然后更新它并返回一个新的 map,它成为 atom 的新值。

如果您愿意,可以重新定义 fn a 以获取第二个参数:

(swap! order
  (fn a [m the-key]
    (update m the-key
      (fn b [t]
        (conj t "Pepperoni"))))
  :toppings)

:toppings 现在作为第二个参数传递给fn a,然后在fn a 内部传递给update。我们可以对update 的第三个参数做同样的事情:

(swap! order
  (fn a [m the-key the-fn]
    (update m the-key the-fn))
  :toppings
  (fn b [t]
    (conj t "Pepperoni")))

现在updatefn a 具有相同的签名,所以我们根本不再需要fn a。我们可以直接提供update 代替fn a

(swap! order update :toppings
  (fn b [t]
    (conj t "Pepperoni")))

但我们可以继续,因为update 还接受更多参数,然后传递给提供给它的函数。我们可以重写fn b 来获取另一个参数:

(swap! order update :toppings
  (fn b [t the-topping]
    (conj t the-topping))
  "Pepperoni"))

再一次,conjfn b 具有相同的签名,所以fn b 是多余的,我们可以使用conj 代替它:

(swap! order update :toppings conj "Pepperoni")

因此,我们最终得到了 minhtuannguyen 的答案。

【讨论】:

    【解决方案2】:

    我会把toppings 变成一个集合。我认为您不希望在集合中出现重复的浇头,所以一组是合适的:

    (defonce order (r/atom {:first-name "" :last-name "" :toppings #{}})) ; #{} instead of []
    

    那么您仍然可以conj 如另一个答案所述:

    (swap! order update :toppings conj "Pepperoni")
    

    但你也可以disj:

    (swap! order update :toppings disj "Pepperoni")
    

    【讨论】:

    • 如果有人想把意大利辣香肠的量翻倍怎么办? ;-)
    • @NathanDavis 够公平的。 :) 使用从顶部名称到数量的哈希映射。例如。 {"pepperoni" 2}。增加(update-in order [:toppings "pepperoni"] inc)dec 减少。当值为 0 时,可能会删除一个条目。
    【解决方案3】:

    您可以使用以下方法更新浇头:

    (swap! order update :toppings conj "Pepperoni")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多