Fork me on GitHub
#reagent
<
2019-10-05
>
chepprey18:10:20

noob q: I'm rendering some table data, and I'm getting a lot of these warnings in my js console: Warning: Every element in a seq should have a unique :key:

chepprey18:10:16

seems like React itself is also warning of something similar/the same: Warning: Each child in a list should have a unique "key" prop

chepprey18:10:36

I have zero experience with React, and minimal cljs experience. Old programmer though. I guess I'm just looking for some basic conceptual understanding of the issue/problem.

p-himik18:10:19

tl;dr: Provide a unique :key metadata value for each child in a lazy collection of children. The value should meaningfully identify a child.

chepprey18:10:22

thanks. It looks like in some examples, they're just using a forever-incrementing number in an atom as a cheap way to produce a unique id. This wouldn't really "meaningfully identify" a child though would it?

chepprey18:10:31

So, would doing this (incrementing numeric technique) make the warning go away, but suffer some performance hit for React?

p-himik18:10:58

Attaching a nonsensical key would result in strange absence of children updates. At least, that's my experience.

p-himik18:10:35

Using just (range) may be fine but only if the values end up in the children as well.

p-himik19:10:18

E.g. like in this React example:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);
Note that in Reagent, you don't have to convert a :key to string explicitly.

p-himik19:10:40

This is the relevant section from the React documentation that goes into detail on why using indices as keys may be a bad idea: https://reactjs.org/docs/lists-and-keys.html#keys

chepprey19:10:44

Thanks, that's definitely a helpful link.

chepprey19:10:31

One observation - this "key" information does not appear to make it out to the "actual DOM" (according to my web inspector), so I presume React only uses this internally, I guess in its shadow DOM.

chepprey19:10:26

I've done web SPAs for a long time, and we leak out all kinds of noise and attributes to the actual DOM. So I'm still adjusting to the Reagent/React way of things.

chepprey19:10:27

(adjusting in this case means: "ok, I added the key stuff, and the warnings stopped, but how come I don't see my key attributes in the domm OHHHHHHHH riiiiiiight React.....)

lilactown19:10:19

yeah, the React link explains the reasoning: when you have a dynamic list of items, in the worst case React has to re-render and re-commit the entire list.

lilactown19:10:00

by adding keys, if they’re meaningful, React can intelligently remove, add or update only the changed children when it re-renders the parent

lilactown19:10:50

which is why using the index of a collection isn’t a good idea: if you remove something from the middle, everyone’s key changes, so React has to re-render and re-commit them because it can’t tell if they’re new or old

p-himik19:10:28

Also, consider installing React Developer Tools addon for your browser. It will display much more information that more closely resembles what you send to the render function.

chepprey02:10:34

Great info, thank you both. In my case I do have a meaningful key in the form of a timestamp (inst). I gave the inst directly as the key. Is it ok to give "objects" like this from clojure, or is it better to explicitly give it a string? Or does it not matter? Does reagent just "toString" it? I can't imagine React would be able to do meaningful things with cljs objects that aren't strings. ..?

chepprey02:10:40

Ooh I just re-read you saying Reagent doesn't need to to explicitly create the string. But React doed operate on a string. Reagent does us the courtesy. I think I'm good.

p-himik03:10:40

Yeah, as long as the resulting string is not [object Object]. 😉