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

Event handlers with modifiers are duplicated when moved up in a keyed each block #4889

Closed
jwlarocque opened this issue May 21, 2020 · 1 comment

Comments

@jwlarocque
Copy link

Describe the bug
Moving an element up in a keyed each block will sometimes duplicate any event handlers in that element which have modifiers.
One additional copy of the handler is added every time the element is moved up.

Logs
Here is a screenshot of the duplicated handler in Firefox. In the source, the element has a single on:click handler, but after moving it up six times, the handler triggers seven times on click.

To Reproduce
This does not occur in the REPL (as far as I can tell). It does occur in both dev and prod modes (npm run dev and npm run build with a separate server).

Here is a rather large app which reproduces the issue 100% of the time, every time on my system: https://github.com/jwlarocque/svelte-dragdropdemo
To reproduce with this app:

  1. Click and drag "Edward" to below the nested list
  2. Inspect the mousedown or mouseenter handlers on one of the items in the nested list (Boston or Chicago for example)
  3. Repeat, moving other items from above to below the nested list, to create additional duplicates

Here is a minimal app which reproduces the issue: https://github.com/jwlarocque/svelte-event-dupe Unfortunately, the issue occurs only intermittently in this minimal version, and I cannot figure out why. Simply click the "swap items" button.

Relevant Source Code App.svelte:
<script>
    import ItemComponent from "./ItemComponent.svelte";

    let data = ["Apples", "Butter"];
</script>

<main>
	<ItemComponent bind:data={data}/>
</main>

ItemComponent.svelte:

<script>
    export let data = [];

    function swap() {
        let temp = data[0];
        data[0] = data[1];
        data[1] = temp;
        data = data;
        console.log("swapped")
    }
</script>

<main>
    <div class="list">
        <button on:click={swap}>Swap Items</button>
        {#each data as datum (datum)}
            <div on:click|stopPropagation={function(ev) {}}>
                <p>{datum}</p>
            </div>
        {/each}
    </div>
</main>

Expected behavior
Moving an item does not duplicate its event handlers.

Information about your Svelte project:

  • Firefox 76.0.1, Chrome 83.0.4103.61

  • Ubuntu 20.04

  • Svelte 3.22.3

  • Rollup

Severity
Low severity for my use case, as there are workarounds.

Workaround
Simply call event methods as you would in vanilla JS instead of using Svelte's modifiers. e.g.,
<div on:click|stopPropagation={function(ev) {handleClick();}}>
becomes
<div on:click={function(ev) {ev.stopPropagation(); handleClick();}}>

I suspect you could also add something like stopImmediatePropagation() to mitigate the side effects/performance impact of this bug for modifiers without a clean vanilla equivalent.

@Conduitry
Copy link
Member

This appears to be a duplicate of #4569.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants