Fork me on GitHub
#reagent
<
2019-09-13
>
jplaza00:09:14

Would this have any adverse perf implications if I use it everywhere?

whoops13:09:51

I wouldn't expect it to

dominicm14:09:24

everywhere = dynamic children, then yes it would.

dominicm14:09:45

React uses the key to determine whether it can just reorder the DOM rather than re-create the node afresh.

jplaza14:09:46

Thanks @dominicm! I started suspecting yesterday that is the cause of my perf problems.

lilactown14:09:03

if you’re using just children, then in the component you can use into

lilactown14:09:26

but when you pass in those children, you should key them

jplaza15:09:19

We have something like this, and almost all of those components are defined using (into [:div] (children this))

(defn product-list
  [products]
  [window
   [view
    [title "Selected products" @(subscribe [:sel-products])]
    [table
     [table-header
      [table-row
       [table-cell ""]
       [table-cell "Name"]
       [table-cell "Price"]]]
     [table-body
      (for [prod (subscribe [:products])]
        ^{:key prod}
        [table-row
         [table-cell [checkbox {:checked (:selected prod)}]]
         [table-cell (:name prod)]
         [table-cell (:price prod)]])]]]
   [app-footer]])

jplaza15:09:34

Every time the subscribe to :sel-products changes, the whole product list is re-rendered

dominicm15:09:28

You probably want to get the id of the product really, or the name if that's unique.

lilactown15:09:15

have you looked at what the key actually is in React DevTools?

lilactown15:09:43

IIRC if you pass in an opaque object it will stringify it to [object Object]

jplaza15:09:05

We are actually using (keep-indexed) and passing i as key. That list of things doesn’t grow or shrink.

jplaza15:09:19

The funny thing is that if I just move [title "Selected Products" @(subscribe [:sel-products])] to a separate component the problem goes away

jplaza15:09:50

What I understand is that deref is triggering a [product-list] re-render and reagent for some reason considers that all of the other components inside it should re-render

jplaza15:09:49

I don’t think there is something wrong with reagent or React, or even re-frame, I think it has something to do with how I’m defining those components -> (into [:div.class] (children this))

dominicm15:09:58

All children are run, then reconciliation happens after.

dominicm15:09:08

That's the normal react behaviour, yep

jplaza17:09:05

Thanks all for your input, finally found the culprit! 🎉 we were passing curried functions as props

[:ul (for [it items] [:li {:on-click (partial handle-click it)} it])]

dominicm19:09:36

Non constant functions can cause issues in some contexts