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

Make exporting empty functions a way to declare component event dispatchers #5602

Open
pushkine opened this issue Oct 28, 2020 · 4 comments
Open

Comments

@pushkine
Copy link
Contributor

pushkine commented Oct 28, 2020

This is a proposal to introduce a more straightforward way to declare component events, namely through the use of empty functions.
Exporting a named function with an empty body would declare an event, and calling that function would dispatch it.

<script lang="ts">
    export function message(msg: string) {}
    message("I just dispatched a message event!");
</script>

The consumer remains the same

<Component on:message={console.log} /> // "I just dispatched a message event!"

This solution comes as a hybrid between prop functions and createEventDispatcher :

export function message(){} export let onMessage = noop createEventDispatcher
on: syntax ❌it's a prop
Event forwarding ❌it's a prop
Amount of listeners ✅ Infinity ❌1 ✅Infinity
Setup ✅ one line ✅ one line ❌>3 lines
"Is there events ?" ✅ it's in the exports ✅ it's in the exports ❌could be anywhere
Arguments ✅ like any function ✅ like any function ❌1 argument
❌wrapped in a CustomEvent
Listener callback ✅ like any function ✅ like any function ❌must destructure CustomEvent
❌must fill type manually
Typings ✅ like any function ✅ like any function ❌troublesome
Refactoring ✅ like any function ✅ like any function ❌troublesome

As a side effect this proposal also introduces the ability to rename events when forwarding them:

<script lang="ts">
    export function hoverLeft(event: MouseEvent) {}
    export function hoverRight(event: MouseEvent) {}
</script>
<button on:mouseover={hoverLeft} /> 
<button on:mouseover={hoverRight} />

The implementation is simple, the compiler just has to fill the body of those functions with createEventDispatcher's :

function message(...args) {
    const listeners = $$self.$$.callbacks.message;
    if (listeners) listeners.slice().forEach((fn) => fn.apply($$self, args))
}

I cannot think of any realistic scenario where this would be a breaking change.

createEventDispatcher has been criticized multiple times #2323 #3488 #4584 #5211 #5597. I for one actively avoid using it. The go-to solution appears to be to introduce yet another reserved variable #5598, I see all of those $$variables slowly creeping up on svelte and I'm very much not looking forward to see another.

@tanhauhau
Copy link
Member

this sounds like a big change, i would suggest open a RFC https://github.com/sveltejs/rfcs/ and have a better discussion over there

@probablykasper
Copy link

probablykasper commented Dec 1, 2021

I like the idea of dispatching an event without having to deal with it being an actual Event object, but some downsides:

  • It's not obvious what it does
  • What if you actually just want to export an empty function as a no-op for whatever reason?
  • You may get warnings for unused arguments
  • With on: you'll have an event without an Event object. You might expect to be able to pass the event to a function that handles all events.
  • It might be confusing to have an event handler take different arguments depending on if it's called from on: or addEventListener.
  • Would not work if you want an argument with the same name as an event

@nbrugger-tgm
Copy link

nbrugger-tgm commented Jun 28, 2022

Hi it might be naive of me thinking this but for me a fix for what @probablykasper said would look like this:

<script lang="ts">
    export message = createEventDispatcher<string>();//message is of type function ()=> string
    message("I just dispatched a message event!");
</script>

This would make it possible to create and export empty functions without messing with the type system.
Would there be any problem with this aproach.

I am a little scared that such a feature will not make it into svelte.

@ethanlal04
Copy link

An awesome idea! I too came up with something very similar called Auto-dispatch. But it has added default behaviour which I think is very powerful. Svelte is about being svelte after all and createEventDispatcher() is just downright ugly. I think this proposal should be seriously considered. And since it has some minor breaking changes, it could be a part of Svelte 5 which is supposed to be a full rewrite of the Svelte compiler with new features and breaking changes anyway.

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

5 participants