DEV Community

loading...
Cover image for Cool bindings with Svelte

Cool bindings with Svelte

jmau111 profile image Julien Maury Originally published at blog.julien-maury.dev ・3 min read

A framework becomes popular because it's useful and it brings value. In that perspective, Svelte has pretty cool features to handle everyday needs I'd like to share with you.

Set state with less code

Look at the following example from the documentation:

<script>
    let count = 0;

    function handleClick() {
        count += 1;
    }
</script>

<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
Enter fullscreen mode Exit fullscreen mode

Source: Svelte assignments

There is some beauty here.

No use to import many tools or write any useState. It's built-in, and the code is amazingly readable.

Passing elements to child components

Maintaining a state between all component tree elements can be a massive pain with reactive frameworks.

I mean you have to write a lot of code, but Svelte is different. Passing elements to children components is straightforward.

<MyChildComponent myProp={myVar} />
Enter fullscreen mode Exit fullscreen mode
<MyGrandChildComponent myProp={myVar} />
Enter fullscreen mode Exit fullscreen mode

The component will re-render when the prop changes, and that covers the whole tree. It does not have to be a var. It can be an expression too.

Basic binding with no effort

If you want to sync states, you can use Svelte data binding. As usual, the syntax is short, and you can also pass data from children this time. It's also called "two-way bindings":

<script>
    let name = '';
</script>

<input bind:value={name} placeholder="enter your name">
<p>Hello {name || 'stranger'}!</p>
Enter fullscreen mode Exit fullscreen mode

Source: Svelte Text Inputs

It means that if var name changes, the input gets updated, and if the user enters its name in the input, the value of the var name changes too.

If we apply this to our nesting components, it could look like that:

<MyChildComponent bind:myProp={myVar} />
Enter fullscreen mode Exit fullscreen mode
<MyGrandChildComponent bind:myProp={myVar} />
Enter fullscreen mode Exit fullscreen mode

All you need for your sync is the simple keyword bind:.

Stay in context

Your component tree might be pretty huge. In that case, passing data, even with data binding, would be exhausting.

To prevent that situation, you can import setContext and getContext from Svelte and start sharing things with the whole family.

Be careful, though. Unlike data binding, it only works downward this time. You set the context in your root component, and all children can access it.

Technically speaking, the context API is a JavaScript map with keys and values. Because Svelte automatically sets an internal state for each component, it's easy to set and get with this map.

In your root component, you can have:

<script>
    import { setContext } from "svelte";

    setContext("YOUR_KEY", {
        foo: "bar"
    });
</script>
Enter fullscreen mode Exit fullscreen mode

And in your child/nested component:

<script>
    import { getContext } from "svelte";

    const { foo } = getContext("YOUR_KEY");
</script>

<p>{foo}</p>
Enter fullscreen mode Exit fullscreen mode

It's pretty cool but remember that it only makes sense if you have a parent-child relationship (nested components). If you need to share something app-wide, you'd probably use stores instead.

Use of the dollar

As we talked about states, there is another excellent feature called "dollar label". It allows for managing side effects.

Perhaps you don't know it yet, but any JavaScript statement can have a label:

yaya: var yiha = "Yiha";
Enter fullscreen mode Exit fullscreen mode

It's a way to associate code instructions with identifiers, but it's not a significant feature. However, Svelte makes it very unique.

IMHO, they hack js labels, but for the best. Do not expect the same "magic" outside Svelte.

Anyway, when you use $ in front of your code, you tell the compiler that your code should re-run every time the values or the expression changes.

What an excellent way to bind things!

<script>
    let count = 1;

    // the `$:` means 're-run whenever these values change'
    $: doubled = count * 2;
    $: quadrupled = doubled * 2;

    function handleClick() {
        count += 1;
    }
</script>

<button on:click={handleClick}>
    Count: {count}
</button>

<p>{count} * 2 = {doubled}</p>
<p>{doubled} * 2 = {quadrupled}</p>
Enter fullscreen mode Exit fullscreen mode

Source: Reactive declarations

Wrap up

There are many more features in Svelte I'm sure you would love too.

Of course, you can achieve more complex bindings and even store data, but I appreciate how Svelte handles common patterns with less code.

I like Svelte because it's not just "less code". You always see the intent. It's amazingly readable.

Photo by Quentin Rey on Unsplash

Discussion (0)

Forem Open with the Forem app