Reputation: 7338
It seems like by default teleport
won't get rendered by using renderToString
.
Does any one know how to render and hydrate the teleport
component in Vue3?
I've found some tests here, but couldn't figure out how to apply this on a real world example, and couldn't find any information on this topic.
Upvotes: 1
Views: 2403
Reputation: 21
As far as I know, teleport in Vue 3 SSR needs special handling: https://vuejs.org/guide/scaling-up/ssr.html#teleports
You can check Evan's answer here:https://github.com/vuejs/core/issues/3869
To hydrate the teleport content, you need to use teleports
property of the SSR context. Then, you need to inject them in the final html. console.log(context)
to see teleports object.
This example may help to solve your problem:
App.vue:
<div class="container">
<teleport to="#teleports">
<toast-notification></toast-notification>
</teleport>
</div>
server.js:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="app">${page}</div>
<div id="teleports">${Object.values(context.teleports)</div>
</body>
</html>
Upvotes: 0
Reputation: 737
Well you can load teleport in ssr, but I am not sure you can hydrate it. Consider this example
html.js
<html>
<head>${context.teleports.head}</head>
<body></body>
</html>
App.vue
<template>
<teleport to="head">
<title>Hello world</title>
<meta name="viewport" content="width=device-width">
</teleport>
<div id="#app">This is app</app>
</template>
Output (html)
<html>
<head>
<title>Hello world</title>
<meta name="viewport" content="width=device-width">
</head>
<body></body>
</html>
Here we are rendering our teleport, so we can set some data even without js. But we cannot hydrate it, as it has nothing to connect to. Instead teleport will be appended another time, and we will get duplicate teleport content.
So all I could do with it, is using this workaround. Before App.vue mounted, we remove old teleport, so new one can replace it. It's not hydration, so it is slower for big components, but it is working well.
App.vue
<script>
export default {
name: 'App.vue',
created() {
if(window !== undefined) document.head.innerHTML = '';
}
}
</script>
Upvotes: 0