Вы не должны использовать атом для этой цели. Ваш код должен выглядеть примерно так:
(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
из библиотеки Tupelo просто добавляет нулевое значение индекса к каждому элементу в коллекция:
(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 antipattern . Использование уникального идентификатора либо из элемента данных (т. Е. Идентификатор пользователя и т. Д. c), либо только из хеш-кода обеспечивает уникальное значение ссылки. Итак, на практике ваш код лучше написать так:
(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