danielrs
danielrs

Reputation: 351

Reactive statement being executed when child reactive statement changes?

I have two reactive statements in Svelte. When the child statement changes (based on some input), the parent statement (statement on which the child statement depends on) is also triggered. Check the following snippet:

<script>
    const options = [
        {key: 'one'},
        {key: 'two'},
        {key: 'three'},
    ];

    // NOTE: initialOption may be obtained reactively from somewhere like the query string.
    $: initialOption = options[0];
    $: selectedOption = initialOption;

    $: console.log('initialOption reactivity:', initialOption);
    $: console.log('selectionOption reactivity:', selectedOption);
</script>

<select bind:value={selectedOption}>
    {#each options as opt}
    <option value={opt}>{opt.key}</option>
    {/each}
</select>

https://svelte.dev/repl/bdc48c75acf94a9ca13da377b7cd8f19?version=3.20.1

If you run the snippet above, each time you try to select from the drop-down (which is bound to selectedOption), the initialOption assignment seems to be re-triggered, why? Is this expected behavior?

Upvotes: 1

Views: 485

Answers (1)

Thomas Hennes
Thomas Hennes

Reputation: 9979

The issue is two-fold:

  • you're assigning objects, which in javascript are assigned by reference and not by value, to your reactive variables
  • one of these variables is also bound (in a two-way binding) to the value property of your select element

When you interact with your select input, you update the value of selectedOption, which in turns updates initialOption (because both variables are references to the same object).

You have two ways to solve this issue:

  1. use scalars instead of objects in your option array
  2. bind to a regular variable instead of a reactive one, and instead use reactive code to initialize the variable

Both approaches are demonstrated in this REPL

Upvotes: 1

Related Questions