6

Edit: it is a bug https://github.com/sveltejs/svelte/pull/7043

Considering the following example one would expect 'bar' to be rendered under the second horizontal rule whenever foo is false and bar[0] is true.

<script>
    let foo = true
    let bar = [false];
</script>

<button on:click={() => foo = !foo}>
    Toggle foo
</button>
<button on:click={() => bar[0] = !bar[0]}>
    Toggle bar
</button>

<hr>
{@html `foo: ${foo}, bar: ${bar.every(x => x)}`}
<hr>

{#if foo}
    foo!
{:else if bar.every(x => x)}
    bar!
{/if}

However, if the following steps are executed, the reactivity seemingly breaks:

  1. Set foo to true
  2. Set bar[0] to true
  3. Set foo to false

Nothing is rendered under the horizontal rule even though the else if block condition is satisfied. This is not the case if the else if condition is simply bar[0], so it seems like using a function is the cause for it not being evaluated. Similar behavior when bar is true before foo is toggled and false after foo is toggled again, unexpectedly 'bar' is rendered at the bottom.

The same effect can be observed when foo is switched between null and [] with the else if condition being Array.isArray(bar).

Is this a bug or am I missing something?

5
  • 2
    I share your feeling that this behaviour is unexpected and wonder too why the else if doesn't seem to be reeveluated when the opening #if condition changes. I can't tell if/why there's a difference between a method call like bar.every(x => x) and the pointer to a value like bar[0], but my solution would be to use a reactive statement for the method call $: condition = bar.every(x => x) and use the variable down below {:else if condition} which seems to work as expected REPL Commented Dec 22, 2021 at 9:20
  • Thanks, that is a pretty good workaround! Still, I'm wondering whether this is desired behavior... Commented Dec 22, 2021 at 10:11
  • 2
    Turns out this is a bug! Tan Li Hau opened a PR to fix it: github.com/sveltejs/svelte/pull/7043 Commented Dec 22, 2021 at 18:09
  • Oh thats pretty cool :) thanks for the info Commented Dec 24, 2021 at 10:04
  • Looks like that issue with reactivity was fixed in mentioned PR and code works. Commented Jun 14, 2023 at 5:58

1 Answer 1

0

Its not really a bug, its kinda expected behaviour in your scenario, when you changed foo to true then bar to true now bar is set and when changed foo to false again bar didn't change if you think about it to trigger reactivity!

the fix for that is to trigger it yourself once any of the values changes:

{#key foo || bar}
    {#if foo}
        foo!
    {:else if bar.every(x => x)}
        bar!
    {/if}
{/key}

Here is a working repl

Sign up to request clarification or add additional context in comments.

3 Comments

Huh, thanks for your answer. Well I kind of expected the else if statement to be reevaluated whenever the if statement changes, as is the case when the else if condition is bar[0]: svelte.dev/repl/429d30493b544231a305f0ea9805f282 here the above steps do not produce the same result. It is weird that some conditions are reevaluated while some are not, really feels like a bug tbh.
@cornzz it is working! svelte.dev/repl/cf252d181c514a309044468c8b734c90
Yes your example is indeed working, I was still referring to my initial example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.