Понимание списка Clojure и уникальные значения для реагента

Предположим, что у нас есть эта сетка со значениями, которые могут быть 0 или 1:

(def grid [[1 0 1]
           [1 0 0]
           [1 0 1]])

Теперь я хочу преобразовать grid в формат html Hiccup, используя понимание списка:

(defn cell-component [is-it-1 key]
  ^{:key key} [:td (if (= is-it-1 1) {:class "is-it-1"})])


(defn grid-html []
  ([:table
   [:tbody
   (for [row grid]
      ^{:key row} [:tr 
                      (for [cell row]
                      (cell-component cell how-i-can-generate-a-index?))])]]))

Таблица сгенерирована правильно, но у меня нет идей, как сделать unique index для моего td. какой how-i-can-generate-a-index? должен быть?


person Michel Uncini    schedule 03.12.2016    source источник
comment
В качестве примечания: круглые скобки вокруг [:table ...] в grid-html избыточны (и код не будет работать с ними, поскольку они преобразуются в вызов функции, а вам просто нужно вернуть компонент: (defn grid-html [] [:table [:tbody ... ]]))   -  person Aleph Aleph    schedule 03.12.2016
comment
Просто используйте map-indexed вместо for.   -  person ClojureMostly    schedule 03.12.2016


Ответы (3)


В вашем случае каждая ячейка однозначно идентифицируется своим индексом в строке. Также было бы более естественно указывать дочерние ключи в родительской структуре, а не в компонентах:

(defn cell-component [is-it-1]
  [:td (if (= is-it-1 1) {:class "is-it-1"})])

(for [[i cell] (map-indexed vector row)]
  ^{:key i} [cell-component cell])

Обратите внимание, что вы должны аналогичным образом назначать ключи на основе индекса для строк - ^{:key row} не будет работать, если в вашей таблице есть дублирующиеся строки.

person Aleph Aleph    schedule 03.12.2016

Вам просто нужно позвонить gensym:

(cell-component cell (gensym))

Это общий способ сделать это. Однако обычно лучше найти в ваших данных какой-то атрибут, который уже обеспечивает уникальную дифференциацию.

Если вы предпочитаете, чтобы числа считались от 0 и выше, вы можете написать свой собственный генератор последовательности:

(def uniq-key (atom -1))
(defn gen-key []
  (swap! uniq-key inc)) 

При первом вызове (gen-key) вы получите 0, второй раз 1 и т. д.

person Chris Murphy    schedule 03.12.2016
comment
Я мог бы это сделать, но с gensym создается новый символ, и вся точка реагента и ключевого атрибута должны иметь уникальный идентификатор в ваших данных. У вас есть идеи, как создать индекс от 0 до (размер сетки * размер сетки)? Если нет, я всегда могу делать то, что вы сказали, и добавлять некоторые метаданные в свои данные. - person Michel Uncini; 03.12.2016

Я рекомендую определять компоненты реагентов, принимая props и children в качестве параметров.

(defn my-li
  [:keys [a-string]]
  [:li
   a-string])

(defn my-list
  [{:keys [color]} & children]
  [:ul
   {:style {:background-color color}}
   (map-indexed #(with-meta %2 {:key %1}) children)])

(defn thelist []
  [my-list
   {:color "#ccc"}
   [my-li "one"]
   [my-li "two"]])

Взято из https://github.com/regent-project/regent/issues/68< /а>

person Jp_    schedule 21.02.2019