Fork me on GitHub
Adam Helins12:11:53

Very weird behavior. On pointerDown , a component transacts and re-renders itself under some condition. When the re-render happens, no click event is triggered (not its own, not from any of its children components (they don't even re-render)), but pointerUp events are all triggered as expected. Logging looks like this: pointerDown -> render -> pointerUp -> click not triggered I've already spent a few hours on this and unless I am doing something terribly wrong, it almost looks like a bug.


Can 'under some condition' be done in a mutation? So both "up" and "down" both simply call a mutation.

Adam Helins15:11:11

Ok so I think I have slightly narrowed it down. It is not exactly the rendering after `down` that seems to be the problem. It is the mutation itself (any other one does not cause this problem). The component in question is generated from a vector of such components. What the down mutation does is ensures that it becomes last in the vector so it is rendered last. This problem happens only when the reordering happens (my 'condition', if not last, make it so). Yes, :keyis properly used as it should. It is as if reordering children on down cancels all immediate click events in those children. What is really puzzling is that immediate up events trigger just fine, proving that a click indeed happened.


I'm afraid I don't know anything about 'generating a component from a vector of components'. To me defsc components are static things, composed together using get-query. I know you can have dynamic queries but I've never needed that feature.

Adam Helins16:11:53

My bad, it was just a poor way of saying that a parent component joins on a list of those components. In other words, when a mutation reorders that list via down on a child, click is mysteriously not fired, but up is. When the mutation does not reorder the list, then the expected happens : down -> up -> click


To understand my own code better I have two functions called get-query1 and get-query* , but they are both just get-query. You mean get-query* , which ends up being a vector of idents in app state. And your mutation is re-ordering these idents within the vector.

👍 3

Also I can't get my head around what 'click' is. You have an up button and a down button that fire their respective mutations. It sounds like you are expecting a mutation to fire a click. The only thing that mutations usually 'fire' are st->st functions.

Adam Helins17:11:19

onClick which is fired after onPointerDown and onPointerUp (supposing all three are being used)


I would have click as a st->st function then. Have onPointerDown and onPointerUp each call one mutation. user event -> mutation -> st->st function.


app state in and app state out. I'll find it in the docs...


They are functions that end in *, by convention.


Just search for * in the book

Adam Helins17:11:46

Right, but the point of those onClick events is that its the standard thing to do. It has defined behavior. I am experimenting and yes, there is something weird about reordering children at onPointerDown or onMouseDown which prevents onClick events from firing.


Oh right dom events. Should be possible to determine one event for one user operation. onClick means mouse has been pressed and released. Funny to have events for both onMouseDown and onClick. I'd want to avoid getting into that situation in the first place 😜

Adam Helins17:11:02

After some experimentation, I have rephrased the problem in my last post. Seems to be a general one. Hopefully it is more understandable.


Can you stick to either Pointer or Mouse events and not combine them? I'd never heard of the Pointer events till now.

Adam Helins17:11:28

Unfortunately it doesn't change anything


onClick doesn't happen when you do something in mouse down. Is that the problem?




And you can't avoid needing to use onClick?

Adam Helins17:11:04

It would mean emulating onClick in a lot of places which would only show how shitty, truly shitty, web programming is 😛


If you are doing something in onMouseDown and something else in onMouseUp, then there is no need to have onClick. Whatever you are doing in onClick can be done in onMouseUp.


Not so much a Fulcro problem but an event bubbling (whatever) problem.

Adam Helins17:11:30

Might be a Fulcro problem maybe due to the mutation system? But could just as well be a problem with React


Can you get the same behaviour with just printing messages, not doing any transacts at all?

Adam Helins17:11:57

Nope, my last post explains this better (I hope)


But in practical terms onClick can always be avoided if you use onMouseUp when only need 'click' functionality, and both onMouseUp and onMouseDown when doing something more involved that needs them both.

Adam Helins18:11:05

Yep, but using onMouseUp instead of a proper click can sometimes result in poor UI behavior. I'll hack something else meanwhile. Heck, the DOM is just one big hack anyway...


Can you have the function that accepts the event (for onMouseDown) be passed in from the parent? So when (transact this ...) , the this is that of the parent?


Any mutation on children should always be transacted from the parent.


I'm really reaching here, but could this be related?

Adam Helins19:11:13

Unfortunately no, those children don't actually need anything from the parent, their query suffice. The parent is a singleton easy to find.


I don't think they are the same... If you have component A, and A re-renders to the dom, and A includes lambdas, those lambdas could be changing out of under you b/c they don't compare =. Not sure if that would change anything though, because the behavior of both lambdas should* be the same.


@UCFG3SDFV Are you using computed to bring any functions that call mutations that affect many children in from the parent? I want to rule that out as an issue.

Adam Helins08:11:32

@U5P29DSUS Right, good lead but it doesn't seem to be the issue. The weirdness would remain anyways since then it would be expected that onPointerUp or onMouseUp would bizarrely not be fired either. @U0D5RN0S1 I see what you mean but lambdas in children are created solely based on their query, they don't need anything from the parent. The plot thickens.


Still good to turn the brain off and always transact 'anything that might be triggered at the child level but apply to all children' from the parent. Good to do that regardless of any theory. Your problem is related to 're-ordering children'.

Adam Helins17:11:08

My previous post seems to be a general problem so I'll try to reword it in general terms. A parent joins on a list of children. Each child registers a onMouseDown, a onMouseUp and an onClick event. A click on a child will fire those events in that order, as expected. BUT. In the case where onMouseDown reorders that list of children via a mutation, inducing a re-render before other events are processed, onClick is mysteriously NOT fired. However, onMouseUp fires as expected. This is weird because the definition of a click is exactly that, mouse or pointer going down and up on the same element. Furthermore, the dom elements don't even move (position: absolute). Nothing mysteriously unmounts/remounts. Re-rendering right after onMouseDown and before other events is not the problem. Reordering the list is. Same happens with onPointerDown and onPointerUp. Children are properly keyed, React does not complain.


all sounds very frustrating! did you try to use a ref and see if it changes somehow? Do you do anything to the event in the onMouseUp? E.g. preventDefault/stopPropagation?

Adam Helins08:11:54

Indeed it is! The ref does not seem to change and I am 100% positive there is no preventDefault or stopPropagation...


happens across all browsers? I guess it sounds like a react/DOM bug.