Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Svelte: Event forwarding with dispatcher vs passing in handling function, which is best practice?

Tags:

svelte

Let's say an Outer component contains an Inner component, and we want an event from the Inner component to be propagated to the Outer component. Without using the store, there are 2 ways to do this:

Method 1: Event forwarding using dispatcher

Inner.svelte: Use Svelte's dispatcher to dispatch a repackaged version of the original event:

<input type="text" on:input={callDispatcher} />

const dispatcher = createEventDispatcher();

function callDispatcher(e) {
    dispatcher("mymsg", {
        foo: e.target.value
    });
}

Outer.svelte: Listen for Inner's dispatched event:

<Inner on:mymsg={handler} />

function handler(e) {
    alert(e.detail.foo);
}

Method 2: Pass Outer's handler directly to Inner

Inner.svelte: Accepts handler passed in by Outer:

export let externalHandler;
<input type="text" on:input={externalHandler} />

Outer.svelte: When Inner event of interest occurs, it will call Outer's handler:

<Inner externalHandler={handler} />

function handler(e) {
    alert(e.target.value);
}

Question

Which one is a better practice? Method 1's dispatcher seems to be an unnecessary middle-layer that not only adds more code but also loses the original event information. But strangely, the Svelte tutorial mentions Method 1 instead of Method 2.

like image 445
moog Avatar asked May 03 '20 04:05

moog


3 Answers

There is no real difference and you can indeed use both. However, method 2 will not work for native elements, leaving you with a mix of both approaches and you get cod like this:

<Child clickHandler="{childClick}" />
<button on:click="{buttonClick}">click</button>

You would always have to remember when to use which one, while if you use the dispatcher method this will always be the same

<Child on:click="{childClick}" />
<button on:click="{buttonClick}">click</button>

The extra dispatcher code is a trade-off in this.

like image 161
Stephane Vanraes Avatar answered Sep 19 '22 03:09

Stephane Vanraes


I find using function prop much simpler, more idiomatic, and does the job elegantly most of the time for me.

<!-- App.svelte -->
<Button onClick={handleClick}></Button>

<!-- Button.svelte -->
<button on:click={onClick}>
  Click me
</button>

The only case I use event forwarding is when I need to do... well... event forwarding. :) (from deeply nested component)

<!-- App.svelte -->
<Outer on:customEvent={handleCustomEvent} />

<!-- Outer.svelte -->
<Inner on:customEvent />

<!-- Inner.svelte -->
<Button on:customEvent />

<!-- Button.svelte -->
<button on:click={() => dispatch('customEvent')}>
  Click me
</button>

Reference: https://www.donielsmith.com/blog/2020-04-21-props-vs-event-dispatcher-svelte-3/

Disclaimer: I'm new to Svelte, coming from React. 🥳

like image 20
Glenn Mohammad Avatar answered Sep 22 '22 03:09

Glenn Mohammad


Adding a link to Why use createEventDispatcher? (Svelte GitHub Issue) comment that covers this nicely, imho:

By using createEventDispatcher, you are telling the compiler to compile your component in such a way that any events it emits adheres to the typical CustomEvent interface. This isn't that big of a deal if you are just dealing with Svelte, but I gather that if you are compiling Svelte components to be used elsewhere as web components, your compiled component will be compiled with an interface other frameworks will understand (…).

This makes sense.

Earlier in the thread:

It's now (Mar 2019) a lot easier to have props that are callbacks in Svelte 3, so you'll probably be using events less anyway.

That suggests there might be some evolutionary reason for the two to co-exist.

One more thing: with events, one is tied to the Custom event interface and the .detail wrapping (that's the whole point!). That may seem like additional complexity to the outer component, whereas with function references one can craft a more slender API.

If one ends up doing function references, notice the <Thing1 {onClick} /> shorthand in the linked issue.


Edit: It doesn't seem that simple. Events are not emitted from components ... (opened Jun 2019) shows that Svelte events aren't fully usable in web components. Until that's resolved, dispatching likely falls in between two worlds. Not really standard. Not really custom.

like image 30
akauppi Avatar answered Sep 22 '22 03:09

akauppi