Svelte from a React developer's perspective. Part 3: Events
Tags: svelte, react, javascript, webdev
Published: 2020-03-02 16:01:07

---
title: Svelte from a React developer's perspective. Part 3: Events
published: true
date: 2020-03-02 00:00:00 UTC
tags: svelte, react, javascript, webdev
canonical_url: https://www.delvalle.dev/posts/svelte-from-react-perspective-part-3/svelte-from-react-perspective-part-3/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/h5jdizijcaljm5nc3nok.jpg
---

Hello, this is the third article where I explore Svelte from a React developer's perspective. The previous articles discussed [The Basics](https://delvalle.dev/posts/svelte-from-react-perspective-basics/svelte-from-react-perspective-part-1/) and the topics of [Reactivity and Props](https://delvalle.dev/posts/svelte-from-react-perspective-basics/svelte-from-react-perspective-part-2/).

In this article I'm gonna take a look at how Svelte manages events and just like the previous articles, I'll provide some quick comparisons to React.

Today's topics introduce some new syntax and approaches that a React dev may not be used to. However, Svelte has kept all these things simple enough for us to get them real quick. The best part of all is that it's still just Javascript.

Let's now talk about:

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#events)Events

We saw some events going on in previous articles. Any Javascript dev familiarized with DOM events, event handling, and event dispatching will feel comfortable with how Svelte does all this.

As seen before, the way you attach event handlers to DOM elements is by sticking the **on:** prefix right before the event name.

Here's how it's done just to refresh the memory:

```html
<input 
  on:change={handleChange}
  ...
>
```

  
And as always, you'll receive the event object via params. 

One thing we can do is to declare the event handlers **inline** using **arrow functions** like so:

```html
<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
    The mouse position is {m.x} x {m.y}
</div>
```

  

Much has been talked about using arrow functions in **React's JSX** and how using them can affect performance due to the functions being destroyed and recreated on each re-render.

However, this is not an issue in Svelte. I'm guessing that due to its **compilation** process, the framework will just create and bind the function once. So we can be sure our performance won't be affected by this practice.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#modifiers)Modifiers

Svelte introduces something called _modifiers_, which help us alter the behavior of our event handlers when we declare them. The syntax will be something like **on:event|modifier={eventHandler}**. The modifiers can be chained as well, like so: **on:event|modifier|modifier={eventHandler}**.

These modifiers will run between the triggering of the event and your handler. So far you can use the following modifiers -_I'm just pasting the list from Svelte's tutorial cause there's nothing more to add_-:

> - preventDefault: calls event.preventDefault() before running the handler. Useful for client-side form handling, for example.
> - stopPropagation: calls event.stopPropagation(), preventing the event from reaching the next element.
> - once: remove the handler after the first time it runs.
> - self: only trigger handler if event.target is the element itself
> - passive — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
> - capture — fires the handler during the capture phase instead of the bubbling phase ([MDN docs](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture))

So far we don't have these in **React** and even tho they are useful I don't see them strictly necessary as you can achieve the same or similar results programmatically when you need to. Still, a very cool feature that will certainly save us some extra lines of code.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#component-events)Component Events

It is most likely that you'll want to dispatch events from your components. You can achieve this by creating an event dispatcher in the component you want to trigger the event from. You can then handle that event on a parent component.

In the example below, we are passing the function **sayHello** to a button element, it will handle the click event on that button. Then, by using the dispatcher we will send another event to the parent component:

```html
<script>
    import { createEventDispatcher } from 'svelte';

    const dispatch = createEventDispatcher();

    function sayHello() {
        dispatch('message', {
            text: 'Hello!'
        });
    }
</script>

<button on:click={sayHello}>
    Click to say hello
</button>
```

  

The **parent** component will then receive the dispatched event in the handler you passed to the **Inner** component.

```html
<script>
    import Inner from './Inner.svelte';

    function handleMessage(event) {
        alert(event.detail.text);
    }
</script>

<Inner on:message={handleMessage}/>
```

  

I don't think it can get simpler than this. Now, I did a small experiment following the approach I am used doing in **React** and it worked just the same. Here I am using a different name for the **on:message** attribute. I am instead passing a **prop** called **onClick** and using it inside the **Inner** component. Now, remember that if we want to use a prop inside a child component we have to do **export let onClick** at the top of our script section.

```html
<script>
    export let onClick;

    function sayHello() {
        onClick('Hello!')
    }
</script>

<button on:click={sayHello}>
    Click to say hello
</button>
```

  
And the parent:

```html
<script>
    import Inner from './Inner.svelte';

    function handleMessage(message) {
        alert(message);
    }
</script>

<Inner onClick={handleMessage}/>
```

  
I wonder why this approach is not in the official tutorial, maybe because of this section talking about events and not about functions as props. You could still be in the need of using a function from a parent component inside a child component, for what you would probably use this approach. 
### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#event-forwarding)Event Forwarding

If you've worked with DOM events you may know that these events _bubble_, meaning that the event is first handled by the element's handler and then it goes up the tree automatically, to each of its ancestors. This doesn't happen with **Component Events** unless you explicitly _forward_ them.

Let's say you have three levels of components. We'll call them **Top** , **Middle** and **Bottom**. If you dispatch an event from the **Bottom** component and want to handle it in the **Top** component, this means the **Middle** component will need to forward that event. Svelte provides us with a very simple way to do it. We just need to declare an empty _on:event_ in our **Middle** component. For example:

**Bottom:**

```html
<script>
    import { createEventDispatcher } from 'svelte';

    const dispatch = createEventDispatcher();

    function sayHello() {
        dispatch('message', {
            text: 'Hello!'
        });
    }
</script>

<button on:click={sayHello}>
    Click to say hello
</button>
```

  

**Middle:**

```html
<script>
    import Bottom from './Bottom.svelte';
</script>

<!-- Empty on:message will forward the event to the Top component -->
<Bottom on:message/>
```

  

**Top:**

```html
<script>
    import Middle from './Middle.svelte';

    function handleMessage(event) {
        alert(event.detail.text);
    }
</script>

<Middle on:message={handleMessage}/>
```

  

You can also forward events on **DOM elements** in case you want to handle the event in a parent component instead of the one where the DOM element lives. Let's say you have a **CustomButton** component but instead of handling the click event in there you forward it to the **Parent**. You would do something like this:

**CustomButton:**

```html
<style>
    /* Some custom styles here */
</style>
<!-- Empty on:message will forward the event to the Parent component -->
<button on:click>
    Click me
</button>
```

  

**Parent:**

```html
<script>
    import CustomButton from './CustomButton.svelte';

    function handleClick() {
        alert('clicked');
    }
</script>

<CustomButton on:click={handleClick}/>
```

  

Pretty simple right? I really like the way how the empty _on:event_ will forward the event to the parent component without any extra code. **React** to me feels the other way around. You would probably pass a handler function as props to the children and let them execute it wherever and whenever necessary. Of course, passing a function as props several levels down can get ugly but this shouldn't happen when taking care of the architecture.

Personally, I would try to avoid forwarding events more than two levels up cause I can imagine myself tracking down the component tree trying to find which component initially dispatched the event. I guess I'll get a better view of this once I start working on an app.

* * *

This is all for the third part, there's still a lot of topics to cover but I'll work on those during the following weeks. Thanks for reading and stay tuned!

*Follow me on twitter: [@jdelvx](https://twitter.com/jdelvx)*