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

Dispatch doesn't work before component is mounted #6106

Closed
thojanssens opened this issue Mar 20, 2021 · 4 comments
Closed

Dispatch doesn't work before component is mounted #6106

thojanssens opened this issue Mar 20, 2021 · 4 comments

Comments

@thojanssens
Copy link

thojanssens commented Mar 20, 2021

Dispatching an event in a reactive statement doesn't work if the component is not yet mounted, see REPL below:
https://svelte.dev/repl/1f0c4745c52147538ee8a39e0a3c3805?version=3.35.0

It works if I execute both:

dispatch('foo', 'hello');
onMount(() => dispatch('foo', 'hello'));

Real use case:
My input components (e.g. Select, TextInput, ...) receive validation props such as required={true}, minLength={3}, etc.
Those components dispatch error events in case the value is not valid. The value is changed on user input, but as the initial value is passed by the parents, and that the parent might change the value as well as those validation props' values, I must check for errors in a reactive statement:
https://svelte.dev/repl/e2e819f5bfba464bbdce6683ea916ee1?version=3.35.0
But when the component is being mounted nothing will be dispatched unfortunately, so I need to duplicate those dispatch instructions to include them inside the onMount callback as well.

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Mar 21, 2021

I can't really comment on the dispatch situation, but to me this doesn't look svelte-esque. I hardly encounter use-cases for dispatch. How about you bind error, type and message so that the outer component can reactively use them? You can also combine them in a single validation object. I don't have time for a full repl, it'd look like this:

<script>
    let validation = {error: false}
</script>

{#if validation.error}
    <div class="error">{validation.message}</div>
{/if}
<Select bind:validation required />




// In the Select component:

<script>
export let validation;
export let required;

let value = '';

$: {
    if (required && !value) {
        validation = {
            error: true,
            type: 'empty',
            message: 'can\'t be blank'
      }
    }
}
</script>

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Mar 21, 2021

I don't have time for a full repl, it'd look like this:

eh https://svelte.dev/repl/6a9c95d9f746499e9e5198d711a88d49?version=3.35.0

What I've learned using Svelte:

  1. Reactivity > events (no need for dispatch)
  2. Stores > promises (no need for {#await})

@Conduitry
Copy link
Member

This has come up before somewhere, although if it was in an issue, I can't find it right now. Essentially, the issue isn't that the event is being emitted before the component is mounted, it's that the event is being emitted synchronously during the instantiation of the component class, and the event listeners aren't attached until after it's instantiated:

	component = new Component({});
	component.$on("foo", /*foo_handler*/ ctx[0]);

To change the behavior of this (and I'm not sure that we'd want to), we'd need some API to attach event listeners to a component as it's being instantiated, rather than after.

Something that would be safer to do now would be to make sure you wait until the next microtask (https://svelte.dev/docs#tick) before emitting the validation status events.

@georgecrawford
Copy link

@Conduitry You might be thinking of this issue: #4470 (comment), and I think your answer here answers my question there (although I’d love to register event callbacks in the component constructor if that is feasible in the future).

In the meantime, what do you think about the Svelte compiler throwing a console error if an event is dispatched during component instantiation? It’s a tricky bug to pin down otherwise!

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

4 participants