paint-brush
Svelte: Communication Between Componentsby@the_rock
6,917 reads
6,917 reads

Svelte: Communication Between Components

by SashaFebruary 26th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Svelte: Communication Between Components - a callback and event dispatcher. A callback method is the way you do communication between components in React.js. A parent component passes a callback method to a child, and then, child invokes it. In this type of communication, a component triggers some events on it's self and then someone (a parent component) will listen to it and do something once triggered. Sveltte allows you to use both of them (as Vue does)

Company Mentioned

Mention Thumbnail
featured image - Svelte: Communication Between Components
Sasha HackerNoon profile picture

In this mini-tutorial we are going to see two different ways of communication between components in Svelte 3: a callback passed as prop and event dispatcher.

Callback communication

A callback method is the way you do communication between components in React. A parent component passes a callback method to a child, and then, child invokes it.

Events based communication

This one is a typical way you do communication in Vue.js (although, it also allows you to use callbacks as props). In this type of communication, a component triggers some events on it's self, and then someone (a parent component) will listen to it and do something once triggered.

Svelte

Svelte allows you to use both of them (as Vue does).

Here we have a simple Guess a Number project. It consist of 3 components: App (parent component), SecretValue (events based communication) and GuessComponent (prop passing). Under the project, there is a detailed explanation of both methods with small snippets, but I think it's better to see a complete project in order to understand better how it works.

App.svelte

<script>
	import { onMount } from "svelte";
	import SecretValue from "./SecretValue.svelte";
	import GuessComponents from "./GuessComponent.svelte";

	let secret = null;
	let showSecret = false;

	const getRandomInt = (min, max) => {
		min = Math.ceil(min);
		max = Math.floor(max);
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}

	const guessNumber = () => {
		showSecret = false;
		secret = getRandomInt(1, 10);
		console.log(secret);
	}

	const onGuess = value => {
		if(value == secret){
			showSecret = true;
		}
	}

	onMount(() => {
		guessNumber();
	});

</script>

<main>
	<h1>Guess a Number</h1>
	<SecretValue showSecret={showSecret} secret={secret} on:restart={guessNumber} />
	<GuessComponents onGuess={onGuess} />
</main>

<style>
	main {
		text-align: center;
		padding: 1em;
		max-width: 240px;
		margin: 0 auto;
	}

	h1 {
		color: #ff3e00;
		text-transform: uppercase;
		font-size: 4em;
		font-weight: 100;
	}

	@media (min-width: 640px) {
		main {
			max-width: none;
		}
	}
</style>

SecretValue.svelte

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

    export let secret = null;
    export let showSecret = false;

    const dispatch = createEventDispatcher();
    
    const playAgain = () => {
        dispatch("restart");
    }

</script>

<div>
    <p>{showSecret ? secret : "???"}</p>
    { #if showSecret }
        <p>You won</p>
        <button on:click={playAgain}>Play again</button>
    { /if }
</div>

GuessComponent.svelte

<script>
    let guessValue = "";
    export let onGuess = null;

    const guess = e => {
        onGuess(guessValue);
    }
</script>

<div>
    <input bind:value={guessValue} />
    <button on:click={guess}>Guess</button>
</div>

Explanation: Event Dispatcher

Let's take a look at SecretValue.svelte. In order to trigger events we must create a dispatcher:

    import { createEventDispatcher } from 'svelte';
    const dispatch = createEventDispatcher();

Now, you can use dispatch object to trigger events on the component:

dispatch("event_name");

To listen to this event in parent component just add

on:event_name
on child and pass a method as a parameter (see App.svelte). The data you want to trigger will be passed as a detail property of the event.

Complete snippet:

<!-- Parent.svelte -->
<script>
    import Child from "./Child.svelte";

    const sayHello = (e) => {
        alert("Hello " + e.detail);
    }
</script>

<Child on:hello={sayHello} />

<!-- Child.svelte -->
<script>
    import { createEventDispatcher } from 'svelte';

    const dispatch = createEventDispatcher();
    
    const triggerEvent = () => {
        dispatch("hello", "Rock");
    }
</script>

<button on:click={triggerEvent}>Call callback</button>

Explanation: Callback

The callback method is very simple: create a function on parent component and pass it to child:

<!-- Parent.svelte -->
<script>
    import Child from "./Child.svelte";
    const callback = (message) => {

    }
</script>

<Child callback={callback} />

<!-- Child.svelte -->
<script>
    export let callback;

    const callCallback = () => {
        callback("test message");
    }
</script>

<button on:click={callback}>Call callback</button>

Which is better?

Personally, I prefer an event-based communication, but I don't think it's actually better. The only problem with props is that it can cause problems if badly managed, but normally, both of them are ok. In real life, I would opt for storage.

You may also be interested in: