sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
79.96k stars 4.25k forks source link

#each block doesn't change when a new state is triggered by a transitioning component inside an #if condition #5734

Open ganigeorgiev opened 3 years ago

ganigeorgiev commented 3 years ago

Describe the bug #each block doesn't change when a new state is triggered by a transitioning component. The weird glitch is happening when the #each block is placed inside an #if in combination with a transitioning component and Promise loaded items.

To Reproduce Please check the following repl - https://svelte.dev/repl/638d0a980c1b47fc8b1e7c270c8e5bc2?version=3.30.1 Click on "Show menu" and then "Clear items". The items array is reasigned (eg. items = []), but the #each block doesn't reflect the change.

Expected behavior The #each block to properly reflect the iterated array state and to be not affected by the transitions of unrelated components.

Workarounds There are a couple of workarounds I found that strangely "fixes" the repl: v1. Remove the transition from Menu.svelte v2. Move the <Menu> component outside the #if block v3. In Menu.svelte change the order of the calls in function changeOption(newOption), aka.:

function changeOption(newOption) {
    hide(); // triggers the transition
    option = newOption;
}

Information about your Svelte project:

kiri2lov commented 3 years ago

It seems the point is that 'isLoading' and 'items' changed at the same time (because the Promise is resolved immediately).

Your example worked correctly after this change:

setTimeout(() => items = [], 0);

now 'items' is updated at the next iteration of the EventLoop.

But the simple case works as expected without this trick: https://svelte.dev/repl/ab0d599bbe084b67b632724e4834876f?version=3.31.0

^^^ UPDATE ^^^

I continued to play with your example and made this change:

if (state == 1) isLoading = false;

https://svelte.dev/repl/b4dc5c7eeca04281a8df050402c1a856?version=3.30.1

The wrong screen was drawn for a moment:

image

This is clearly not what should have happened. After a second, the screen refreshed as it should.

ganigeorgiev commented 3 years ago

@kiri2lov I'm confused. Your example doesn't seem to reflect the same problem. In real application the issue happens even when the promise is not resolved immediately. In addition this doesn't explain why the position of the menu component matter or why removing the transitions "fixes" the issue.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

ganigeorgiev commented 3 years ago

@pngwn The issue is still reproducible with the latest svelte version - https://svelte.dev/repl/638d0a980c1b47fc8b1e7c270c8e5bc2?version=3.38.3

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

ganigeorgiev commented 2 years ago

The issue still could be reproduced with the latest svelte version (3.44.3) - https://svelte.dev/repl/638d0a980c1b47fc8b1e7c270c8e5bc2?version=3.44.3

mstoltenburg commented 2 years ago

I experienced quite the same problem …