Fork me on GitHub
#reagent
<
2021-03-22
>
achikin14:03:51

Dummy question - can I set react keys like this? [:div {:key 123}]

p-himik14:03:04

And just in case - if that comes up because of for or something similar, you can avoid using keys altogether by just (into [] ...).

chepprey20:03:44

Do array indices become the key?

chepprey20:03:17

... as regarded by reagent?

p-himik20:03:39

When you're using a vector, there's no longer a need for keys.

juhoteperi10:03:28

Every vector element becomes separate children to React element, (non sense example): [:div 1 2 3 4 5] React.createElement("div", null, 1, 2, 3, 4, 5); vs [:div (for [i (range] i))] React.createElement("div", null, [1, 2, 3, 4, 5]); React has different way to render these. The second one, where it has children that is a Array, each children needs the key. With large lists React can update DOM more efficiently if it has the keys for each element. E.g. if you have list with 1000 items, if you remove the first item from list, if you don't have keys, React would have to do 999 DOM updates. If you have keys, React needs to just do 1 DOM update. So not using keys and concatenating items into vector is not a general solution to avoid using keys.

p-himik10:03:53

So will a scaled up version of

[:div
  (for [k (get-thousands-of-keys)]
    ^{:key k} [some-complex-component (get-params k)])]
be more efficient in terms of re-rendering a single item than
(into [:div]
  (map (fn [k]
         [some--complex-component (get-params k)]))
  (get-thousands-of-keys))
?

juhoteperi10:03:24

Probably the difference is quite small if the order and the set of items is same for each render. Difference is most obvious if React has to add some DOM elements between old elements or such.

p-himik10:03:27

Ah, right. So reordering would be more efficient as well, it makes sense.

thheller10:03:53

FWIW this benchmark is useful comparison for keyed vs. non-keyed differences https://krausest.github.io/js-framework-benchmark/2021/table_chrome_89.0.4389.72.html

thheller10:03:06

keyed is faster for certain ops and non-keyed for others

thheller10:03:44

so depending on how your items change it might be better to use one or the other. it can be significant.

p-himik10:03:47

Hold old. How can you compare? Between keyed and non-keyed tables, React versions are different. And Reagent is not even present in the latter.

thheller10:03:39

just compare react. the version difference doesn't matter much.

juhoteperi10:03:46

There is separate implementation for keyed / non-keyed version. Reagent only has keyed implementation for that benchmark.

thheller10:03:58

nowadays the implementations are pretty good across the board so keyed is pretty much a no brainer in all situations

p-himik10:03:29

Then the results are very strange. Swapping two rows without keys is more than an order of magnitude faster than with keys.

p-himik10:03:48

Keys have another disadvantage - it's not always easy to come up with the right key given a set of complex props.

thheller10:03:53

yes, because of the underlying dom operation it does

thheller10:03:48

non-keyed it changes the text of 2 dom elements but doesn't move them. so the browser doesn't need to perform a layout/style recacluation

thheller10:03:07

for keyed it moves the dom elements and it needs to recalc the whole list in the worst case

p-himik10:03:43

Then why keyed would be a no-brainer, given that you still have to put extra responsibility on yourself to select the right key generation algorithm?

thheller10:03:49

well most of the time you have some natural keys anyways

thheller10:03:12

the into thing is pretty much the worst thing you can do performance wise but it is the only option to go non-keyed

thheller10:03:44

so that will almost certainly lose to a keyed impl

p-himik10:03:25

Suppose I have a collection of entities with IDs and a bunch of text values that I need to display. That ID is natural, yes, so it makes sense to set it as a key. But those text values can change without any change to the ID. Won't using ID as a key prevent the items from being re-rendered when one of the text values changes? I definitely remember falling into a version of such a trap before, where there was an obvious natural key that ended up preventing the components from being re-rendered when needed.

thheller10:03:23

but if you look at inferno for example the difference in swap rows for keyed/non-keyed is much smaller

thheller10:03:37

so it is much more an artifact of how react handles this not general

thheller10:03:02

no the key only controls ordering, it does not affect other updates

juhoteperi10:03:02

Id controls the component lifecycle and is used for DOM reconcilation, if component properties change, it will be re-rendered, key doesn't matter.

p-himik10:03:48

Hmm, perhaps I'm much more confused than I thought. Thanks for the info, I'll experiment with it.

lilactown14:03:04

> Won't using ID as a key prevent the items from being re-rendered when one of the text values changes? it will still re-render, but the way it changes the DOM and the component lifecycle may be different. keys are especially useful if you're trying to manage input/focus/component state/etc. in a list - you don't want React to blow away your DOM and component state of of all your rows if some data changes and you swap two rows

👍 3
juhoteperi10:03:28

Every vector element becomes separate children to React element, (non sense example): [:div 1 2 3 4 5] React.createElement("div", null, 1, 2, 3, 4, 5); vs [:div (for [i (range] i))] React.createElement("div", null, [1, 2, 3, 4, 5]); React has different way to render these. The second one, where it has children that is a Array, each children needs the key. With large lists React can update DOM more efficiently if it has the keys for each element. E.g. if you have list with 1000 items, if you remove the first item from list, if you don't have keys, React would have to do 999 DOM updates. If you have keys, React needs to just do 1 DOM update. So not using keys and concatenating items into vector is not a general solution to avoid using keys.