'Error in Svelte component when switching pages
I have a project that uses Svelte + Laravel + Inertia, I'm working on a page that has a paging feature for records. But when I change the page number an error is displayed in the console and the application stops working.
app.js:108643
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'removeChild')
at detach (app.js:108643:19)
at Object.d (app.js:83321:77)
at Object.d (app.js:83428:16)
at destroy_component (app.js:110453:32)
at Object.d (app.js:81565:73)
at Object.d (app.js:80366:38)
at destroy_component (app.js:110453:32)
at Object.d (app.js:81393:73)
at Object.d (app.js:81640:43)
at destroy_component (app.js:110453:32)
After doing some tests, I found the problem: Inside my component I have the Inertia Link component, and it is causing the error, because if I change the component to a simple tag, the error stops.
Component code
<script>
import { onMount } from "svelte";
import { Link } from "@inertiajs/inertia-svelte";
import { icon as make } from "@fortawesome/fontawesome-svg-core";
export let icon, title, click, attributes, href;
const svg_uid = Math.random().toString(16).substring(2);
onMount( () => {
const svg = make(icon).node[0];
document.querySelector(`svg[data-fa-svg="${svg_uid}"]`).replaceWith(svg);
const button = svg.parentElement;
for (const attribute in attributes) {
button.setAttribute(attribute, attributes[attribute])
}
})
</script>
<!--
---------------------------------------
HTML Template
---------------------------------------
-->
{#if click}
<button type="button" {title} class="svg-button-component" on:click={click}>
<svg data-fa-svg="{svg_uid}"></svg>
</button>
{:else if href}
<Link {href} {title}>
<svg data-fa-svg="{svg_uid}"></svg>
</Link>
{:else}
<svg data-fa-svg="{svg_uid}"></svg>
{/if}
Working code (Thanks @dummdidumm)
<script>
import { onMount } from "svelte";
import { icon as make } from "@fortawesome/fontawesome-svg-core";
import { Link } from "@inertiajs/inertia-svelte";
export let icon, button, href;
const uid = Math.random().toString(16).substring(2);
onMount( () => {
if (href) {
document.querySelector(`a[data-fa-svg="${uid}"]`)
.appendChild(
make(icon).node[0]
)
} else {
document.querySelector(`svg[data-fa-svg="${uid}"]`)
.replaceWith(
make(icon).node[0]
)
}
})
</script>
<!--
---------------------------------------
HTML Template
---------------------------------------
-->
{#if button}
<button type="button" {...$$restProps} class="svg-button-component" on:click>
<svg data-fa-svg="{uid}"></svg>
</button>
{:else if href}
<Link {href} {...$$restProps} data-fa-svg={uid}></Link>
{:else}
<svg data-fa-svg="{uid}" {...$$restProps}></svg>
{/if}
Solution 1:[1]
The problem isn't the Link component, it's that the code replaces the svg elements imperatively with different elements. Svelte can't know that and keeps a reference to the old (now removed) svg element that is a child of Link. When the component is destroyed, it tries to remove that nonexistent element and therefore the error is thrown. Either you adjust your code to not imperatively modify the code, or you add a wrapper element around the element you replace, like
<Link>
<span>
<svg ...>
</span>
</Link>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dummdidumm |
