试剂 React Clojurescript 警告:序列中的每个元素都应该有一个唯一的 :key。

16

我从这里复制了一个两年前的代码片段。现在已经可以与Figwheel一起使用,并使用了更新的Reagent/React版本。

我正在寻找一种通用的方法来隔离这个警告消息,该消息在JavaScript控制台中显示:Warning: Every element in a seq should have a unique :key。想法是在所有组件中放置一个具有生成唯一值的:key,然后这些警告消息应该会消失,我就可以知道哪些组件需要独特的:key了。我的问题是即使在所有组件中都放置了独特的:key,警告消息仍然出现。

所以,有人能告诉我错过了哪个组件或者我做错了什么吗?如你在源代码(永久链接)中看到的,我已经在第43和68行的两个组件中添加了:key (gen-key)

编辑 所以这就是答案(永久链接),至少就代码而言。只需要查找第44和60行处的^{:key (gen-key)}的位置即可。

请注意,函数gen-key是为了调试而创建的。应该替换成自然键。

你可以这样实现gen-key

(defn gen-key []
  (gensym "key-"))

这是上述链接中提到的方法:

(def uniqkey (atom 0))
(defn gen-key []
  (let [res (swap! uniqkey inc)]
    (u/log res)
    res))
2个回答

21

Reagent项目网站的示例中

(defn lister [items]
  [:ul
   (for [item items]
     ^{:key item} [:li "Item " item])])

(defn lister-user []
  [:div
   "Here is a list:"
   [lister (range 3)]])
注意:上面的 ^{:key item} 部分在这个简单的例子中并不是必要的,但是为动态生成的组件列表中的每个项目附加一个唯一键是一种良好的实践,并有助于React提高处理大型列表的性能。键可以像此示例中一样作为元数据给出,也可以作为组件的第一个参数中的 :key 项(如果它是一个映射)。请参阅React的文档以获取更多信息。
而关于动态子节点的React文档应该会指导你朝正确的方向前进。在高层次上,如果你有一些代码在某种循环中生成了许多相似的组件,你需要在每个组件前缀每个组件的 ^{:key val}。然而,由于reagent需要将事物封装在向量中,因此通常需要将循环结构的输出包装在其他向量中,例如上面示例中的 [:ul] 或在一般情况下的 [:div] 中。我有时使用这种类型的构造 (into [:div] (for ....)) 来完成这个任务。

代码使用map而不是forinto,但效果相同。我已经尝试过将:key作为元数据或作为组件的第一个参数。但根据文档无论哪种方式都没有关系。在[:polyline]中放置了许多x y点 - 没有:key - 也许这就是问题所在 - 我仍然在努力解决... - Chris Murphy
3
在组件中,元数据必须是作为元素的第一个形式 ^{:key val} [component] 而不是直接放在组件内。请注意,reagent 无法很好地处理 lazy-seq,因此您经常会看到像 (into []...)(doall ...) 这样的内容以确保 seq 被实现。请确保使用最新的 reagent 版本,因为错误消息已经得到了一些改进。我记得上次遇到错误时看到了 reactid 的引用,所以您可以使用浏览器检查器来查看页面元素,以了解哪个组件负责该问题。 - Tim X
1
在day8/re-fram的维基上有一些优秀的reagent文档,可能会有所帮助。特别是,https://github.com/Day8/re-frame/wiki/Using-%5B%5D-instead-of-%28%29 可能有助于理解reagent将创建哪些React组件,这并不总是很明显,可能有助于追踪您需要元数据的位置。 - Tim X
那个(into [:div] (for ....))的一般情况非常有用。我想补充一点,如果它是一个[:svg]组件,可以用[:g]来替代[:div]来包含它。 - Chris Murphy
@TimX 该文档已经移动到此处 https://github.com/reagent-project/reagent/blob/master/doc/UsingSquareBracketsInsteadOfParens.md - TankorSmash

4
我认为你需要将:key作为元数据提供,例如:
^{:key (gen-key)} [:polyline ...

我认为只能将其作为组件的地图条目添加,就像您在此处所做的那样:


[trending-app {:key (gen-key) :state-ref paths-ratom :comms ch}]

所以上述方法有效,但不适用于例如以下情况。
[:svg {:key (gen-key)

我尝试将 ^ {:key (gen-key)} 放在 [:polyline[:svg 的前面。到目前为止还没有成功。另外,在 [trending-app 中不需要任何东西,我会在源代码中进行修复。您能否在答案中提供文档参考? - Chris Murphy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接