Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOM replacement breaks when a component child is in the middle of an out animation #5808

Closed
awmcclain opened this issue Dec 17, 2020 · 5 comments · Fixed by #5849
Closed

Comments

@awmcclain
Copy link

Describe the bug
There's a race condition when you replace a component that has a child with an out transition that is currently running, svelte dies.

In production, we see the old component stay on the page in addition to the component replacing it, and we don't see any console errors on this (with svelte 3.29.4).

In REPL there's an exception and JS dies.

Logs
Uncaught (in promise): if_block.p is not a function (only in REPL, version 3.31.0)

To Reproduce
https://svelte.dev/repl/46686d49624a4f099f738998fbe5301c?version=3.31.0

Expected behavior
Out transition of the child would be killed, the whole component would be replaced.

Information about your Svelte project:

  • Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10)
    tested in chrome and safari

  • Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc)
    OS X

  • Svelte version (Please check you can reproduce the issue with the latest release!)
    3.29.4 and 3.31.0

  • Whether your project uses Webpack or Rollup

Severity
How severe an issue is this bug to you? Is this annoying, blocking some users, blocking an upgrade or blocking your usage of Svelte entirely?

We can work around it (also shown in the REPL) but it's a real gotcha, especially with production code that has nested components.

@christiankaindl
Copy link

christiankaindl commented Dec 27, 2020

I got the same error and found a fix for it. The problem is the {:else} block. If you split the code up into two separate if-blocks everything works as expected.

This is your example from above, but with the fix applied:
https://svelte.dev/repl/dbba868b5fa64be4b750b9296c6f5cfa?version=3.31.0

You can toggle really fast and nothing breaks

@awmcclain
Copy link
Author

Good sleuthing!

In looking at our source code, it turns out that it wasn't an {:else} block that was causing problems -- it was an interval.

Here's an updated REPL that still breaks -- it looks like there's a race condition going on, where the onInterval is updating the {#if} block but for some reason the onDestroy isn't getting called when the parent is swapped out, so then it leaves everything in the DOM.

Should this be a different issue?

https://svelte.dev/repl/3defa9a68e7147ec8a18a4a15d422c36?version=3.29.4

@mdynnl
Copy link

mdynnl commented Dec 28, 2020

related #5815

@Conduitry
Copy link
Member

This is fixed in 3.31.2 - https://svelte.dev/repl/46686d49624a4f099f738998fbe5301c?version=3.31.2

@awmcclain
Copy link
Author

The other repro case is still broken, unfortunately (the old divs aren't cleared, onDestroy() doesn't get called).
https://svelte.dev/repl/3defa9a68e7147ec8a18a4a15d422c36?version=3.31.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants