Fork me on GitHub
#reagent
<
2019-09-10
>
juhoteperi10:09:56

I've just deployed 0.9.0-rc1 version to Clojars: https://clojars.org/reagent/versions/0.9.0-rc1 and I'd like to hear if this works in existing projects or if someone will notice regressions: https://github.com/reagent-project/reagent/issues/449

parrot 20
šŸŽ‰ 4
šŸ‘ 4
šŸ™‚ 4
mikerod16:09:37

@roman01la I canā€™t even find a relevant issue anywhere out there for reagent (or a discussion) explaining what is/was wrong. Can you?

Roman Liutikov16:09:00

Couldnā€™t find it as well

mikerod16:09:23

getting closer

mikerod16:09:12

also, is it just me or does new jira always seem super slow and frustrating

mikerod16:09:58

I give up I guess for now, but https://clojure.atlassian.net/browse/CLJS-3002 was as close as I got to some enlightenment

Roman Liutikov16:09:33

Hm, how's this issue related to the above problem in reagent?

mikerod17:09:43

@roman01la Itā€™s hard to say for sure. Iā€™m guessing it has to do with the apparent inability to determine that the arity is supported

mikerod17:09:52

could not be the correct lead - itā€™s just the closest I found

juhoteperi18:09:17

Huh, the caution about Reagent in clojurescript-site is from july, but I don't have any idea what it is about.

mikerod18:09:59

guess itā€™d be asking David Nolen at this point, probably on #cljs-dev to dig it out

devn18:09:30

I'm probably going to struggle to come up with a way to describe the problem I'm having, but here goes: NOTE: I am new to reagent and react. I have a mostly working drag and drop implementation. There is a sidebar of li elements. When I drag element at index 3 and drop it elsewhere, the item is removed, and elements from the new index 3-N are then broken and no longer draggable. However, the elements 0-2 are.

manutter5118:09:06

I could make a wild guess: you render your list, and then attach handlers to each li element for the drag-n-drop support. Then you drag an element, and React says, ā€œAha, this list has changed, I need to rerender everything after the Nth element,ā€ so it re-renders them, but since itā€™s React doing it, it only renders the elements, it doesnā€™t apply your handlers.

devn18:09:40

There's context missing here, and it's a bit of a mess at the moment, but please take a look and let me know if anything looks amiss. https://gist.github.com/devn/6b6254013728fe2b952d71f83ed782ce

devn18:09:32

Updated to show where rule-component is called.

devn18:09:20

Other notes: I know the sorted-set looks a little suspect, but I've tried the same thing as a vector, and it's the same issue.

devn18:09:39

@U06CM8C3V You may well be right, but I'm not sure how to fix what I have if that is the case. Wanna take a peek and let me know what you think?

manutter5118:09:17

Yeah, Iā€™m looking at it now ā€” Iā€™m a re-frame person more than a reagent person, but let me dig in a bit more

manutter5119:09:35

One thing you might try as a debugging step is add a println or js/console.log between (fn rule-component* [rule db] and [:li, and print out the name of the rule or something. If React is re-rendering everything after the dragged-rule, youā€™ll see a bunch of debug statements spam out when you drag/drop.

manutter5119:09:12

And if not then thereā€™s some other problem.

devn19:09:54

@U06CM8C3V yeah, that's what's happening alright

devn19:09:51

Any thoughts on fixing this?

manutter5119:09:56

Itā€™s a little odd, you have the li elements rendering with handlers in-line, so it shouldnā€™t be a question of React rendering them without the handlers

manutter5119:09:42

Itā€™s possible that React is rendering a whole new rule-component (the top-level defn), but re-using the individual li elements for the sake of efficiency.

manutter5119:09:59

Or, hereā€™s a guess: React re-renders the main rule-component and the first 0-N li elements, but re-uses the N-last li elements. So since the rule-component defines atoms for everything, a new rule-component would have all new atoms, but some of the li elements would still be pointing back at the atoms in the original rule-component, so theyā€™d break.

devn19:09:31

my head hurts šŸ˜„

manutter5119:09:36

Or possibly some variation on that idea, which you could test by putting a println or something right after (defn rule-component [rule db] ā€¦

manutter5119:09:48

Mine too! šŸ˜„

devn19:09:48

@U06CM8C3V hmmm, I don't see anything interesting by dropping a println there. I see the full list of items on initial render, but nothing after drag.

devn19:09:14

(and drop)

manutter5119:09:25

Anyway, my first approach to trying to fix it would be to make the ul element an entirely separate component from the li element.

manutter5119:09:52

Hmm, so maybe itā€™s not calling rule-component multiple times :thinking_face:

manutter5119:09:27

I havenā€™t tried implementing drag and drop, but it does seem like the state management here is head-achy. Then again, re-frame keeps everything in one big atom, so maybe Iā€™m just letting my re-frame bias creep in.

devn19:09:14

@U06CM8C3V if it's not too much trouble, would you mind providing ane example of what you mean? How would you wrap the ul bit in a separate component?

manutter5119:09:42

Iā€™m trying to figure that out right now, may take me a bit šŸ™‚

devn19:09:13

thanks so much for your help. i've been beating my head against this for nearly 2 days and I could use some help

manutter5119:09:40

Looking at this more closely, Iā€™m starting to doubt that it will actually help to make the ul tag separate ā€” I was thinking there was more state in the parent, but it looks like itā€™s all local to each li element.

manutter5119:09:14

Have you tried putting all your handler functions above the (fn rulecomponent* [rule db] line? Move ā€™em up to the let statement and have your li components use like :on-drag-start drag-start-handler, :on-drag-end drag-end-handler etc?

manutter5119:09:05

Your current code is re-creating those handlers every time React re-renders one of them, maybe it would help if the handlers were just defined once.

devn19:09:54

hmmm, you're saying define {:class ...} in the block, and then just reference it as {:class stuff}?

manutter5119:09:47

no, just the :on-drag-foo bits

manutter5119:09:22

So like after the let definition for disabled?, youā€™d have

drag-start-handler (on-this-target
                     (fn [e]
                       (let [[effect rule] (rule/drag-effect-and-rule rule)]
                         ...

devn19:09:48

so the let block would look like [on-drag-start (...)], and then I'd do {:class [] :on-drag-start on-drag-start}

manutter5119:09:05

Yeah, thatā€™s it

manutter5119:09:09

The static stuff like :class, :id, :key, etc, stays down below, and all :on-whatever handler functions move up.

devn19:09:53

here goes nothin'

devn19:09:11

šŸ˜ž same issue

devn19:09:25

this is killing me, man

manutter5119:09:54

What specifically happens when you try the second drag-n-drop?

manutter5119:09:23

And also, does your ā€œhoverā€ functionality work, or is that also broken?

devn19:09:53

On the first one, I get logging that tells me which rule I've selected, what I'm hovering over, etc. I see the account of available items decrease by 1, and the item is removed from the available items list. The available item directly after that item is given a class "dragged" which does not go away. For our purposes, this item now, and every item after it are treated as the previous dragged rule. So for instance, if the list were:

1. A
2. B
3. C
and we initially dragged A, B's class would be set to dragged (among other things), and if we try to drag B, the logging shows the name of B is actually the previous rule we dragged (A).

devn19:09:29

Hover works, but not after the first drag and drop. It gets locked onto the target of the drop.

devn19:09:03

I'd like to give you a demo of it, but redacting everything would be a royal pain.

manutter5119:09:37

Yeah, no, I may not need it, Iā€™m having an ā€œOMG not this againā€ momentā€¦

manutter5119:09:00

I think I know what this may be

manutter5119:09:25

Is there some unique piece of information in rule thatā€™s different for every li element?

devn19:09:58

yes, its :id

devn19:09:42

you may notice that :id and :key are set

devn19:09:50

both to be the value of :id

manutter5119:09:31

Awesome, try this: inside rule-component*, just before the [:li, put ^{:key (str 'rule-comp-" (:id rule)}

devn19:09:59

<li title="Drag onto a rule grouping on the left." draggable="true" id="d9212b48-3751-46d9-8776-51aa769593cd" class="card"><span>Foo</span></li>

manutter5119:09:00

(Hoping this works the same in reagent as in re-frame šŸ¤ž )

devn19:09:23

oooo, you know, i think i tried this, but here goes

devn19:09:50

err no, i did it on the [rule-component r db] bit inside the when

manutter5119:09:53

If itā€™s what I think it is, you have to have it on the :li

devn19:09:01

you got me really excited, but still no dice. hmmmm

manutter5119:09:05

:thinking_face:

devn19:09:57

ohhh, hmm, let me try a different palce

devn20:09:21

perhaps the available-list [rule-component r db] bit

devn20:09:23

that did it!

devn20:09:26

YESSSSSSSSSSSSS

manutter5120:09:17

This is amazing. Every time Iā€™ve come across a weird, unsolvable React/Reagent/re-frame issue itā€™s this same fix.

manutter5120:09:54

I should just start answering every question in #reagent with ā€œDid you put a unique key on the element thatā€™s giving you trouble?ā€

devn20:09:43

So, I thought that [:li {:key (:id rule) ...}] would do it for me.

devn20:09:06

and then while reading the reagent docs I came across the use of the ^{:key ...} metadata, and tried it, but in the wrong place.

manutter5120:09:20

Yeah, I donā€™t know if itā€™s supposed to work inside the component, but putting it in the meta has always worked for me.

devn20:09:29

it needed to be very specifically, on the calling component that generates the underlying li

devn20:09:47

it didn't work to tag the :li in the rule-component* fn itself

devn20:09:24

oh, one more question: is there a reason for the prefix? Is that so React knows they're all friends and need to be taken care of together?

manutter5120:09:41

Ok, Iā€™ve seen similar stuff, didnā€™t think it would work in this case, but fortunately you thought to try it.

manutter5120:09:19

I just use a prefix as a ā€œbest practiceā€ in case I need to use the same key in 2 diff components

manutter5120:09:51

Itā€™s probably overkill in most cases, but maybe someday itā€™ll save me a really weird bug.

devn20:09:27

gotcha, and actually, in this case, that may wind up being an issue. the target of the drop is also a rule-component

manutter5120:09:01

there you go then šŸ˜‰

devn20:09:14

šŸ˜„ man, i owe you a beer or whatever your preferred beverage of choice is

manutter5120:09:05

Np, glad I could help, youā€™ve expanded my repertoire of React stories that all have the same punch line.

devn20:09:39

You hear the one about React? I know you haven't, because the key to it needs to be different every time. :drum_with_drumsticks:

devn20:09:47

(Meh, needs some work)

devn20:09:41

No but seriously, can you explain this?

devn20:09:14

I mean, you've done enough already, and I'm looking at our 81 (now 82) message conversation, but I would like to understand the underlying need for this change.

manutter5120:09:44

Iā€™m not 100% clear on it myself, but my rough guess is that React wants to minimize the number of DOM elements that have to be re-rendered, and they use the keys to track which elements have already been rendered. For whatever reason, it sometimes holds on to already-rendered DOM elements when it shouldnā€™t, and thus elements fail to change as expected. Manually specifying the key forces React to keep components straight when it would otherwise confuse them.

jahson21:09:58

The main reason is the reconcilation in react

šŸ‘ 4
devn18:09:03

I am completely flummoxed as to how to debug what's causing the problem. Any help would be greatly appreciated.

juhoteperi18:09:17

Huh, the caution about Reagent in clojurescript-site is from july, but I don't have any idea what it is about.