Fork me on GitHub
#reagent
<
2017-10-22
>
emccue00:10:50

Really dumb question, but how does r/atom work exactly?

emccue00:10:57

I'm trying to implement a similar system in regular ol' javascript, but don't know how to proceed from this point (where I just have a dumb version of a regular atom)

mhuebert10:10:12

@emccue I posted a little explanation of how r/atom works in the re-frame channel yesterday: https://clojurians.slack.com/archives/C073DKH9P/p1508598109000063 should probably try to put it somewhere else, like a blog post šŸ˜œ

mhuebert10:10:11

the specific answer for your question would depend on what youā€™re trying to do next with your ā€˜special atomā€™. are you trying to associate some other chunks of code with ā€˜dependenciesā€™ (eg. r/atomā€™s that were dereferenced during execution of that code), to re-run that chunk whenever one of its dependencies changes? if so, a starting point for thinking about the problem might be: somehow that chunk of code needs to be wrapped to ā€˜observeā€™ which ā€˜special atomsā€™ are dereferenced during evaluation, and the ā€˜special atomā€™ needs to be modified slightly during dereference to see if any of these ā€˜observorsā€™ are present

metametadata11:10:28

@emccue in JS land you can try taking cues from https://github.com/mobxjs/mobx

wpcarro14:10:09

Does anyone know a good way to forcibly prevent re-agent from re-rendering a component? Iā€™ve tried :should-component-update (constantly false), but to no avail

wpcarro14:10:31

Iā€™ve heard that using :key can also help

wpcarro14:10:15

also, does anyone know, which of these is preferable from a reagent architecture standpoint?

;; within a parent component's `render` function
(when @(rf/subscribe [:search/active?])
  [search/render])
vs.
;; within the search component's render
(defn render []
  (when @(rf/subscribe [:search/active?])
    ;; ...

wpcarro14:10:23

My suspicion is that the latter is preferable since reagent will register the reaction at the search component level instead of the parent component. Is this a fair assumption?

wpcarro14:10:25

These two questions may seem unrelated, but when I refactored from the former example to the latter, my need for :should-component-update (constantly false) or :key both went away, so Iā€™m tempted to assume I did the right thing

pesterhazy15:10:12

@wpcarro it might help if you explained your problem in terms of what you wanted to accomplish

pesterhazy15:10:16

re: the 2nd question, the 2nd option should be preferable, because fewer React Elements need to be rerendered

wpcarro15:10:25

@pesterhazy good call. Apologiesā€¦ I have a D3 canvas that has been rendering unexpectedly after a certain, unrelated change to app-db. I have fixed the solution by refactoring (shown above). I was primarily looking for validation about the change. Iā€™m still unsure as to why reagent cannot keep track of my D3 canvas without the presence of ^{:key "constant"} or something similar

wpcarro15:10:00

What makes things additionally confusing to me is that reagent does not re-render the D3 canvas in these two scenariosā€¦

;; 1.
;; within a parent component's `render` function
[search/render @(rf/subscribe [:search/active?])]
and
;; 2.
;; within the search component's render
(defn render []
  (when @(rf/subscribe [:search/active?])
    ;; ...
but not in this third example
;; 3.
;; within a parent component's `render` function
(when @(rf/subscribe [:search/active?])
  [search/render])

wpcarro15:10:55

Why should examples 1 and 3 affect the way that reagent keeps track of the D3 canvas (which is a sibling component to the search)

pesterhazy15:10:03

@wpcarro which ones re-render in your opinion?

wpcarro15:10:52

@pesterhazy Iā€™m using clairvoyant and re-frame-tracer, which tell me that main (ie ā€œparent componentā€), search, and canvas are all rendering when [:search/active?] changes its value in examples 1 and 3.

wpcarro15:10:40

It makes sense that main and search would render under these circumstances, but not canvas since the props provided to it have not changed nor has any of its subscription values changed

pesterhazy15:10:41

what exactly is confusing to you?

wpcarro15:10:07

why would the position of the (@rf/subscribe ...) calls affect the rendering of the canvas component when both subscribes are in the parent component?

p-himik15:10:47

@wpcarro You provide examples for search, but ask about canvas. Should the examples read canvas in place of search?

pesterhazy15:10:55

sorry I'm not understanding what is canvas, search etc... none of these appear in the code?

pesterhazy15:10:12

can you put up a minimal repro gist?

wpcarro15:10:52

@p-himik good question. No the examples should read search in this case. Will post a gist involving main and canvas

pesterhazy15:10:13

if you deref an ratom anywhere in a fn, the whole component will rerender if its value changes

pesterhazy15:10:30

that's why it's useful to move derefs into child components

wpcarro15:10:21

in main.cljs in both versions 1 & 2, the derefing is happening in main/render Why should the outcomes of the render fn change?

pesterhazy15:10:57

and you fixed it by adding keys?

pesterhazy15:10:37

then I think I know what the "problem" is

wpcarro15:10:50

strangely enough version 1 does not render canvas while version 2 doesā€¦

pesterhazy15:10:06

in v2, you insert an element into the dom, depending on whether :search/active? is true

pesterhazy15:10:58

React's diffing algorithm isn't smart enough to detect [:a :b] and [:b] as variants of each other

pesterhazy15:10:47

it checks the first element: "It was :a: but now it's :b. How could that be the same tree? So I'll just give up and throw away the existing DOM and recreate everything."

pesterhazy15:10:55

The reconciliation is based on heuristics. A more complex algorithm would do the right thing here, but it would take too long to run.

pesterhazy15:10:13

So you need to help React by providing hints.

pesterhazy15:10:17

You can add keys.

pesterhazy15:10:49

You could also wrap the (when ...) in a div so the overall Dom structure remains the same.

pesterhazy15:10:44

Usually oaccsional re-mounts don't matter much, but because you're using a stateful component, you want to keep it mounted at all cost

wpcarro16:10:28

so because [:a :b] is considered entirely different from [:b], React throws away [:a :b] instead of just throwing away :a ā€¦ is that right?

wpcarro16:10:22

seems like conditional renders like (when predicate [:dom]) are dangerous

pesterhazy16:10:52

Yeah it just says "screw it, I can't reconcile those in a graceful style"

pesterhazy16:10:06

it is dangerous, unless you add keys (which is good practice anyway)

wpcarro16:10:23

lovely! so when I moved the subs to the children components, it prevented main from rendering, and I avoided the risk altogether

wpcarro16:10:38

in other words, Reactā€™s diff algo didnā€™t even need to run

pesterhazy16:10:40

you subtly changed the dom structure

pesterhazy16:10:10

note that the same issue would appear in React proper I think - it's not Reagent specific

wpcarro16:10:12

I feel like I should use :key on the canvas to prevent regressions

wpcarro16:10:22

@pesterhazy thatā€™s what it sounds like to me

pesterhazy16:10:55

I've scratched my head over this precise issue before

wpcarro16:10:18

thatā€™s great thoughā€¦ I think I totally understand whatā€™s going on now

pesterhazy16:10:33

happy to hear that!

p-himik16:10:35

I've asked a question on re-frame's Github issue about complex components: https://github.com/Day8/re-frame/issues/264#issuecomment-338485510 I hope to get more visibility to the issue itself and maybe to get some ideas from the people in this channel.