Fork me on GitHub
#reagent
<
2022-06-30
>
pinkfrog03:06:41

First question is why the first identical? gives true, and the second question is why the second identical is false.

(let [a (r/render [app] (.getElementById js/document "app"))
        b (r/render [app] (.getElementById js/document "app"))]
    ;; true
    (identical? a b))

  (let [a (r/render [#'app] (.getElementById js/document "app"))
        b (r/render [#'app] (.getElementById js/document "app"))]
    ;; false
    (identical? a b))

pinkfrog03:06:54

For the first case, I just tested

(identical? [app] [app])
gives false. Dunno how the (identical? r/render,,,) result is true.

lilactown04:06:16

what type is returned by r/render?

pinkfrog04:06:08

It is reagent/render function. The return is a react component.

thheller05:06:59

#' in CLJS is a hack, it always returns a new cljs.core.Var and as such is never identical? given that CLJS doesn't usually have vars at runtime

👀 1
thheller05:06:21

so as far as reagent is concerned these are different vars (and as such different components)

pinkfrog06:06:15

> #' in CLJS is a hack, it always returns a new cljs.core.Var and as such is never identical? given that CLJS doesn’t usually have vars at runtime Yes. I just tried that out.

pinkfrog06:06:56

I wonder how the caching mechanism works. Given this code

(let [a (r/render [app] (.getElementById js/document "app"))
        b (r/render [app] (.getElementById js/document "app"))]
    ;; true
    (identical? a b))
It returnes the SAME component. Their must be some caching based on the value [app].

thheller06:06:15

pretty sure thats just what react-dom/render returns and it bind something to the dom #app element and returns that if the mounted component was the same

pinkfrog06:06:20

But regarding reagent, when it sees [app], it should create some new instance right? And that instance happens to be equal (by value) to the already mounted instance?

thheller06:06:31

no, this is all react. reagent basically just constructs a react element and tells react to render that

thheller06:06:54

so react compares those elements and if its the same component triggers and update

thheller06:06:06

if its different it triggers a replacement

thheller06:06:20

on the second call I mean. on the first it triggers a mount in either case.

pinkfrog06:06:24

So how does react tell two components are equal or not?

thheller06:06:38

literal (identical? a b)

pinkfrog06:06:43

Does js has some operator overloading functionality for the equal == operatoror

thheller06:06:10

JS does not no, but that is not needed here

thheller06:06:39

you can do

(let [x #'app
      a (r/render [x] (.getElementById js/document "app"))
      b (r/render [x] (.getElementById js/document "app"))]
  ;; true
  (identical? a b))

thheller06:06:55

didn't try but pretty sure that'll be identical again

pinkfrog06:06:24

Let me clarify my question, the input [app] is fed into some reagent function first, and that result is then fed to react. My question is, does reagent return the same instance? Given your response, it should, because react use (identical?) to test component equality. Then given that, there must be some caching mechanism on reagent to achieve the purpose of returning the same instance.

thheller06:06:53

and I answered that. all r/render does is call (r/as-element [app]) and then (react-dom/render that-element some-extra-callback)

thheller06:06:40

so no, reagent doesn't cache anything here. it is react that is doing that. but also not technically a cache. it just checks if it mounted something on the DOM #app previously. if so it re-uses that and updates or replaces it.

thheller06:06:49

I have not used reagent myself, but I spent a fair amount of time with react so this is all assuming it works similar to other react wrappers. fairly confident it all works like this but you should verify.

pinkfrog06:06:16

You are right. I need digest the react comparison logic abit.

pinkfrog06:06:45

My intuition is that, since

(identical? (r/as-element [app])
              (r/as-element [app]))
Is false. So react should return two different components, but instead it returns the same one. There must be something ongoing.

thheller06:06:21

it does return the same? that is news to me. then I guess it does some caching?

thheller06:06:46

oh wait. it does not return the same. so yeah it is not reagent caching.

pinkfrog06:06:56

This is my original question:

(let [a (r/render [app] (.getElementById js/document "app"))
        b (r/render [app] (.getElementById js/document "app"))]
    ;; true
    (identical? a b))
The r/render returns identical result.

thheller06:06:19

yes, but this is react doing that

pinkfrog06:06:47

Yes. That boils how react does the comparison. Can you guide me the relevant docs?

thheller06:06:50

I mean basically just call (react-dom/render (r/as-element [app]) (.getElementById js/document "app") )

pinkfrog06:06:16

Yes. I am on the same page.

thheller06:06:36

no clue about docs. I just looked through the react sources a while ago

pinkfrog06:06:34

Ah. Is it because while the react element is different, the undelrying react component is the same (the app component) where as [app] is the element. React compares based on the component instead of elements.

pinkfrog06:06:59

And that might also answers why

(let [a (r/render [#'app] (.getElementById js/document "app"))
        b (r/render [#'app] (.getElementById js/document "app"))]
    ;; false
    (identical? a b))
Because each time #’app is a new component.

thheller06:06:11

thats what I said earlier yes 😉

pinkfrog06:06:43

I should have …. 😂

pinkfrog06:06:45

Thanks for the help!