I had written a Svelte component that accepted a prop, and I wanted to destructure some variables from that prop. But I wanted this destructuring to be reactive, so that the variables would update if the prop updated.
My code looked something like this:
<script>
export let post;
// doesn't work
let { title, body, description } = post;
</script>
<div>{title} {body} {description}</div>
Svelte Only Runs the Script Once
The first problem here is that this is not reactive.
When the post
prop changed, the title
, body
, and description
values weren’t being updated, because Svelte only runs the <script>
code once.
To make it reactive, I needed a $:
to tell Svelte to watch those variables. So I tried sticking a $:
in front:
<script>
export let post;
// still doesn't work
$: let { title, body, description } = post;
</script>
<div>{title} {body} {description}</div>
That doesn’t work, though.
Can’t Use $:
Before a Variable Declaration
You can’t declare variables with let
/const
/var
on a reactive $:
line. Which makes sense if you think about it…
Svelte is going to re-run this one line when post
changes, but you can’t re-run a variable declaration. That’d be just as syntactically invalid as doing
let title;
let title; // error!
So it makes sense that Svelte doesn’t allow it.
Ok, fine, take out the let
:
<script>
export let post;
// STILL doesn't work
$: { title, body, description } = post;
</script>
<div>{title} {body} {description}</div>
But this still didn’t work. Destructuring a variable without declaring some new variables is not valid JavaScript, so it doesn’t work in Svelte either.
You can’t do { a, b, c } = whatever
in JavaScript – you’d need a let
or const
in front to make that valid.
Here’s the fix: wrap the whole thing in parentheses
This works:
<script>
export let post;
// this works!
$: ({ title, body, description } = post);
</script>
<div>{title} {body} {description}</div>
This is how to destructure variables in JavaScript when you aren’t declaring them at the same time, and so this is how it works in Svelte, too.
With that change made, this component was working as expected, re-rendering when the prop changed and updating the destructured variables too.