svelte: Infinite loop when binding to an item in a for loop
Describe the bug
The page freezes when I attempt to iterate through a map containing a class and bind a freshly created element using data from that class into a field of that class. This appears to be related to #6921 Considering that one of my cores spikes up to 100%, there is probably some infinite loop going on. I am a beginner, so I am sorry if I am making some rookie mistake
Reproduction
I have this example:
<script lang="ts">
import "../app.css";
import {NavbarRoute} from "../lib/NavbarRoute.ts";
import {onMount} from "svelte";
let beforeShop = new Map<string, NavbarRoute>;
beforeShop.set("/", new NavbarRoute("Home"));
beforeShop.set("/tos", new NavbarRoute("Pravidla a GDPR"));
let afterShop = new Map<string, NavbarRoute>;
afterShop.set("/team", new NavbarRoute("Tým"));
afterShop.set("/hire", new NavbarRoute("Nábory"))
afterShop.set("/contact", new NavbarRoute("Kontakt"));
onMount(function () {
let route;
route = beforeShop.get(window.location.pathname);
if (route == undefined) route = afterShop.get(window.location.pathname);
if (route) {
let div = route.div;
div.classList.add("tab-active");
}
})
</script>
<header>
<div class="bg-base-100 w-screen inline-flex items-center pt-2 pb-2">
<div class="w-1/2 justify-start"></div>
<div class="flex-shrink-0 inline-flex">
<div>
{#each [...beforeShop] as [path, route]}
<nav-el bind:this={route.div}>{route.name}</nav-el>
{/each}
<nav-el>Wiki</nav-el>
</div>
<div>
<nav-el class="bg-primary text-base-100 rounded-box">Shop</nav-el>
</div>
<div>
{#each [...afterShop] as [path, route]}
<nav-el bind:this={route.div}>{route.name}</nav-el>
{/each}
</div>
</div>
<div class="w-1/2 justify-end flex">
<nav-el class="">Přihlásit se</nav-el>
</div>
</div>
</header>
NavbarRoute:
export class NavbarRoute {
public div: any | undefined;
constructor(public name: string) {
this.div = undefined;
}
}
By commenting out some parts of the code, I’ve found out, that it hangs due to: bind:this={route.div}
Logs
Nothing showed up in the server and browser logs.
System Info
System:
OS: Linux 5.18 Arch Linux
CPU: (24) x64 AMD Ryzen 9 5900X 12-Core Processor
Memory: 44.10 GB / 62.71 GB
Container: Yes
Shell: 5.1.16 - /bin/bash
Binaries:
Node: 16.16.0 - /usr/bin/node
Yarn: 1.22.19 - /usr/bin/yarn
npm: 8.15.1 - /usr/bin/npm
Browsers:
Chromium: 104.0.5112.79
Firefox: 103.0.1
npmPackages:
svelte: ^3.44.0 => 3.49.0
Severity
blocking all usage of svelte
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16 (12 by maintainers)
This is fixed in Svelte 5, because dependencies are tracked at runtime and the infinite loop is thus avoided
I’ve been triaging Svelte issues for well over a year now and seen every single issue and this comes up regularly, it is definitely not fixed (at least not every variation of it). I even ran into it myself over year ago https://github.com/sveltejs/svelte/issues/6298
To make this very clear, here is a REPL https://svelte.dev/repl/5f436e05809346a38baf906184321761?version=3.49.0 It logs
objtwice, for no reason.I was able to track this down to the use of the spread operator. Or more specifically cloning the array,
sliceworks too. Here’s the absolute minimal REPLhttps://svelte.dev/repl/d8f6f4532ab04a1fa028d1835d55839e?version=3.49.0
The first two each cause infinite loops, the third does not.
SvelteKit offers a whole host of information for this precise purpose. E.g. https://kit.svelte.dev/docs/modules#$app-stores-page allows you to access the current URL on both server and client.
If you follow the Getting Started https://kit.svelte.dev/docs/introduction#getting-started you can see that in the demo app:
https://github.com/sveltejs/kit/blob/5cd8385391e30ecf525d11d24c268d3b08284dfb/packages/create-svelte/templates/default/src/lib/header/Header.svelte
Edit: I recommend checking out the demo app before working with an empty project.