Daevid66
Daevid66

Reputation: 51

Watch svelte components object properties in for each block without triggering multiple change updates

I have some problem understanding how change detection in Svelte works for components wrapped in an each block.

If you want to watch for changes to primitive property on a components you can do it like this:

export let value = 0;
$: valueChanged(value);
function valueChanged(value) {
  console.log("value changed", value, "for object", id);
}

This works great; the handler is only triggered on one component and only when the value property is changed.

But if you try to do the same for a object or array property, like this:

export let data = { prop: "test" };
$: dataChanged(data);
function dataChanged(data) {
  console.log("data has change for object", id);
}

This watcher will be triggered whenever you make any change to any components data.

You can see a REPL here: https://svelte.dev/repl/7ae1392c29614ccbbd67ab67a7dedc63?version=3.29.0

If you click on the buttons, and open the browser console, you will see that clicking on the buttons gives very different results.

Can you give me an idea of how to improve my code so that change detection is only once also for the object/array case?

Upvotes: 2

Views: 1696

Answers (1)

Daevid66
Daevid66

Reputation: 51

I got a response on the Svelte discord by 'pngwn' that gave me this answer:

'Use immutable = true in the child component and it will only update when the components props are not equal (===) But in order to make this work when passing objects as props you need to make sure your structures are immutable, so replace the object when updating the data prop'

A link to forked REPL: https://svelte.dev/repl/f58ae8dc08a942f8a46b6cbc1337a665?version=3.29.0

Upvotes: 3

Related Questions