How to replace the contents of a target in Svelte instead of appending to children?

Viewed 3242

Calling new Component({ target }) appends component to target, I want to replace all the old content of the target with the new component. How can I do that?

3 Answers

If you're hydrating server-rendered markup, it's better to use the hydrate: true option (docs here).

If target was previously occupied by a Svelte component, it's better to call that component's $destroy() method.

Otherwise, the simplest way is to just empty out the target element:

target.innerHTML = '';
new Component({ target });
function replaceTarget (target) {
    const component = new MySvelteComponent({
        target: target.parentElement,
        anchor: target,
    });
    target.remove();
}

This prepends the new component just before the target element (in the target's parent), and then removes the target.

Relevant documentation on anchor: https://svelte.dev/docs#Creating_a_component

Probably not a good idea to use with target === <body>.

I had this same problem, I was creating HTML fallbacks separately and simply wanted to hydrate the whole dom with client-side Svelte components that exactly mirror the static html. However, using the method from the docs was creating two nested <html> elements because it was appending to the target instead of replacing it.

Grabbing the "parent" of the element I want to replace seemed to work for me:

import App from './App.svelte';

let target = document.querySelector('html').parentNode;

new App({
  target: target,
  hydrate: true
});

In my specific case that could more simply be written as:

import App from './App.svelte';

new App({
  target: document,
  hydrate: true
});

Replacing the top level <html> element will give some console errors, but here are screenshots and more details for how we're implementing it in our project in case it's helpful: https://github.com/plentico/plenti/issues/65#issuecomment-696391302

Related