mzzzzb
mzzzzb

Reputation: 1452

svelte reactive assignment run unexpectedly

I have a simple component with two dropdowns where value of first dropdown controls options on the second one.

enter image description here

REPL to full code

Whenever the first dropdown (Layout) changes, I want the first available option on the second dropdown (Lesson) to be selected. To acheive this, I have this reactive assignment on line 28

$ : lessonkey = validLessons[0].id 

I would expect this line to ONLY execute when validLessons changes ? But I find this line executes even when the second (Lesson) dropdown changes resulting in the first option always being selected. Could somebody point out what is the issue with this code.

Upvotes: 0

Views: 162

Answers (1)

Geoff Rich
Geoff Rich

Reputation: 5482

The root issue seems to be a Svelte bug with reactivity and select bindings. If you look at the generated code, validLessons is invalidated when the second select value is changed.

    function select1_change_handler() {
        lessonkey = select_value(this);
        ((($$invalidate(1, lessonkey), $$invalidate(2, validLessons)), $$invalidate(5, layout)), $$invalidate(0, layoutkey));
        (($$invalidate(2, validLessons), $$invalidate(5, layout)), $$invalidate(0, layoutkey));
    }

I don't see why this should happen. However, because validLessons is invalidated, your lessonkey reactive statement is being re-run.

One way to work around this is to make the dependency on layoutkey explicit so that we no longer have a dependency on validLessons. If the behavior you want is "reset the lesson dropdown when the layout dropdown changes", you can also write the following:

    $ : validLessons = lessons.filter(lesson => layout.script.some(s=> s==lesson.script))
    $ : layout = layouts.find(l => l.id == layoutkey)
    $ : lesson = validLessons.find(l => l.id == lessonkey)
    $: if (layoutkey) setFirstLesson();
    
    function setFirstLesson() {
        lessonkey = validLessons[0].id
    }

Now, reactive statement #4 only depends on layoutkey, so it will only re-run when layoutkey changes (and not validLessons). This is because Svelte only looks at values that appear in that statement, and not variables that appear in the function called by that statement (so, layoutkey is a dependency, and validLessons is not).

Upvotes: 1

Related Questions