【问题标题】:How to reset a counter in Re-frame (ClojureScript)如何在 Re-frame (ClojureScript) 中重置计数器
【发布时间】:2020-02-26 22:50:09
【问题描述】:

这一定是每个人在学习新框架时都会发现的那些愚蠢/复杂的事情之一。所以我有这个功能:

(defn display-questions-list
 []
 (let [counter (atom 1)]
     [:div
      (doall (for [question @(rf/subscribe [:questions])]
            ^{:key (swap! counter inc)} [question-item (assoc question :counter @counter)])])))

@counter 原子不保存任何重要数据,它只是一个“可视”计数器,用于显示列表中的数字。第一次加载页面时,一切正常,如果列表显示五个问题(1..5),问题是创建/编辑/删除订阅问题时:

 @(rf/subscribe [:questions])

再次调用,然后当然会显示列表,但现在从 6 到 11。所以我需要一种方法来重置 @counter。

【问题讨论】:

    标签: clojurescript reagent re-frame


    【解决方案1】:

    您不应该为此目的使用原子。您的代码应该看起来更像这样:

      (ns tst.demo.core
        (:use tupelo.test)
        (:require [tupelo.core :as t]))
    
      (defn display-questions-list
        []
        [:div
         (let [questions @(rf/subscribe [:questions])]
           (doall (for [[idx question] (t/indexed questions)]
                    ^{:key idx}
                    [question-item (assoc question :counter idx) ])))])
    

    tupelo.core/indexed 函数从 the Tupelo library 简单地 prepends a zero-based index value 到集合中的每个项目:

    (t/indexed [:a :b :c :d :e]) =>   
    
        ([0 :a] 
         [1 :b] 
         [2 :c] 
         [3 :d] 
         [4 :e])
    

    源代码很简单:

    (defn zip-lazy
      "Usage:  (zip-lazy coll1 coll2 ...)
    
          (zip-lazy xs ys zs) => [ [x0 y0 z0]
                                   [x1 y1 z1]
                                   [x2 y2 z2]
                                   ... ]
    
      Returns a lazy result. Will truncate to the length of the shortest collection.
      A convenience wrapper for `(map vector coll1 coll2 ...)`.  "
      [& colls]  
      (assert #(every? sequential? colls))
      (apply map vector colls))
    
    (defn indexed
      "Given one or more collections, returns a sequence of indexed tuples from the collections:
          (indexed xs ys zs) -> [ [0 x0 y0 z0]
                                  [1 x1 y1 z1]
                                  [2 x2 y2 z2]
                                  ... ] "
      [& colls]
      (apply zip-lazy (range) colls))
    

    更新

    实际上,:key 元数据的主要目标是为列表中的每个项目提供一个稳定 ID 值。由于项目可能有不同的顺序,使用列表索引值实际上是一个 React 反模式。使用数据元素内的唯一 ID(即用户 ID 等)或仅使用哈希码提供唯一的参考值。所以,在实践中你的代码最好这样写:

    (defn display-questions-list
      []
      [:div
       (doall (for [question @(rf/subscribe [:questions])]
                ^{:key (hash question)}
                [question-item (assoc question :counter idx)]))])
    

    一些哈希码示例:

    (hash 1)                   =>  1392991556
    (hash :a)                  => -2123407586
    (hash {:a 1, :b [2 3 4]})  =>   383153859
    

    【讨论】:

    • 如果你不想要外部库,clojure core 中也有map-indexed
    猜你喜欢
    • 1970-01-01
    • 2019-07-18
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多