SvelteKit Rendering a Random Prop is different between server and client
Solution 1:
You have a few options here:
- Set the random numbers in onMount so they're only set on the client. This will cause a FOUC, however, since the box won't be server rendered.
<script>
import { onMount } from 'svelte';
let t, l;
onMount(() => {
t = Math.random() * 90;
l = Math.random() * 90;
})
</script>
{#if t && l }
<div class="box" style="--t: {t}vh; --l: {l}vw;"></div>
{/if}
<style>
.box {
position: fixed;
top: var(--t); left: var(--l);
width: 10vw; height: 10vh;
background-color: black;
transition: all 1s;
}
</style>
- Generate the random numbers inside a server endpoint that you fetch in the load function. Since SvelteKit caches the result of fetches inside load, this should use the same random numbers on both client and server.
// random.json.js
export async function get() {
return {
body: {
t: Math.random() * 90,
l: Math.random() * 90,
},
};
}
<!-- index.svelte -->
<script context="module">
export async function load({ fetch }) {
// this will be cached, so it will be the same on client & server
const result = await fetch('/random.json');
const { t, l } = await result.json();
return {
props: {
t, l
}
}
}
</script>
<script>
export let t;
export let l;
</script>
<div class="box" style="--t: {t}vh; --l: {l}vw;"></div>
<style>
.box {
position: fixed;
top: var(--t); left: var(--l);
width: 10vw; height: 10vh;
background-color: black;
transition: all 1s;
}
</style>
Personally, I like the second option better, since there's no FOUC.