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>
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} />
<MyGrandChildComponent myProp={myVar} />
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>
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} />
<MyGrandChildComponent bind:myProp={myVar} />
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>
And in your child/nested component:
<script>
import { getContext } from "svelte";
const { foo } = getContext("YOUR_KEY");
</script>
<p>{foo}</p>
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";
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>
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 you write better code: less wordy blocks, better readability.