Here is how you might render a list of items into DOM nodes in Reagent.

;; Works, but returns React warning to have a unique key for each array child
(def cars ["Tesla" "BMW" "Mercedes"])
[:ul
(for [car cars]
^{:key item} [:li car])]

will generate the following HTML, along with WARNINGS:

  • Tesla
  • BMW
  • Mercedes

The Problem

React needs to know a list of [:li]’s uniqueness to accomplish performant renders on large lists. When a [:li] tags are generated dynamically, React won’t be able to tell if they were shuffled around, so we assign unique keys to each element.

The Solution

The solution is to generate [:li]’s with meta data representing unique keys:

(def cars ["Tesla" "BMW" "Mercedes"])

(defn create-index-for-each-element [coll]
(map-indexed (fn [index item]
[index item]) coll))

;; Better option, no React warning, each child in array has unique "key" prop
[:ul
(let [indexed-items (create-index-for-each-element cars)]
;; indexed-items is a seq ([0 "Tesla"] [1 "BMW"] [2 "Mercedes"])
(for [[index item] indexed-items]
^{:key index} [:li item]))]

will generate the following, without warnings:

  • Tesla
  • BMW
  • Mercedes




Resources: