Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Click events are registered twice when two leptos custom elements are on a page #2564

Closed
SorenHolstHansen opened this issue Apr 28, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@SorenHolstHansen
Copy link

SorenHolstHansen commented Apr 28, 2024

Describe the bug
You can find a repro case here.

I have defined two web components using your custom-elements crate with leptos as the component framework. The components are very simple to show the bug and are just a button with a click handler. However when embedding both on a site, whenever clicking one of the buttons, two click events are registered (See the video in the repro repo).

If I tried to add the buttons in raw "js", that is, through web-sys with add_event_listener; then only one click event is registered which leads me to think this is a Leptos problem.

You can see a video of the issue here:

Screen.Recording.2024-04-28.at.23.55.58.mov

I hope it makes sense, please tell me if this belongs in the custom-elements repo instead.

Leptos Dependencies

leptos = { version = "0.6.11", features = ["csr"] }

To Reproduce
Steps to reproduce the behavior:

  1. See https://github.com/SorenHolstHansen/leptos-custom-elements-double-click

Expected behavior
I would expect only one click event being sent when clicking the button

@gbj
Copy link
Collaborator

gbj commented Apr 29, 2024

If you opt out of event delegation by using on:click:undelegated does it work as expected? (I have not tried)

@gbj gbj added the bug Something isn't working label Apr 29, 2024
@SorenHolstHansen
Copy link
Author

Yeah, that seems to fix it, thanks! Is there some way to do this simpler? I am not the biggest fan of having to put that flag on all event handlers

@SorenHolstHansen
Copy link
Author

I tried merging the two components into one crate, so the "run" function defines both custom components, and that seemed to fix the issue as well

@gbj
Copy link
Collaborator

gbj commented Aug 19, 2024

So for the sake of clarity/closing this one out: There are several issues here interacting to cause this problem.

  1. Leptos uses event delegation by default, which means that on: events are delegated to the window. When an event fires, the framework manually finds the correct listener on an actual element. The framework also keeps track of which events it has already created listeners for on the window, precisely so that it does not add multiple click listeners to window, for example, each of which calls the listener multiple timess.
  2. However, you were defining the two components in separate crates. Essentially, you were shipping multiple copies of Leptos the framework itself, each of which was running independently of the other. So each one thought it had not added a click event handler to window yet. However, each one added a separate listener, which meant the click handler was called twice.

0.7 (which is the main branch now) makes delegation opt-in — event delegation has generated enough minor confusion in edge cases over time that it's worth making it an opt-in feature rather than the default IMO.

In general, I would also suggest that merging the components into one crate/one WASM binary is always preferable, if it is at all possible; otherwise you end up shipping much more code to the client. i.e., say the binary size of Leptos the framework is K, and the cost of your two components are A and B. If you compile the two crates separately, you are shipping A + B + 2K to the client, as opposed to A + B + K.

@gbj gbj closed this as completed Aug 19, 2024
@SorenHolstHansen
Copy link
Author

SorenHolstHansen commented Sep 17, 2024

Thanks for the write-up! Just a quick follow up, then.

Is it a bad idea to split your leptos app in multiple libs, say one for ui, one for the main app, and so on? I.e. are we adding multiple leptos "instances" on top of each other? Or is that just the case for wasm?

@gbj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants