I'm new to Sveltekit, and having issues trying to return Svelte components from the server.
I'm migrating settings for a nav menu in Sveltekit from a client-side .svelte component to a server load() function.
Currently, I have a nav menu in routes/+layout.svelte
, and use a dict to define the menu items. The icons for each menu item are svelte components from a 3rd party library.
//routes/+layout.svelte
<script>
import {ArrowLeftOnRectangleIcon, Cog6ToothIcon, UserCircleIcon} from "@babeard/svelte-heroicons/mini";
import NavMenu from "@components/NavMenu.svelte";
const menuSettings = {
menuButtonIcon: UserCircleIcon,
menuItems: [
{title: 'Settings', icon: Cog6ToothIcon, url: '/app/settings', current: false},
{title: 'Sign Out', icon: ArrowLeftOnRectangleIcon, url: '/app/sign-out', current: false},
]
}
</script>
<NavMenu {...menuSettings} />
<slot />
I now want to move those menu settings to a server load() function, so that I can determine which menu items to show server-side.
<!--routes/+layout.svelte-->
<script>
import NavMenu from "@components/NavMenu.svelte";
export let data;
</script>
<NavMenu {...data.menuSettings} />
<slot />
//routes/+layout.server.js
import {ArrowLeftOnRectangleIcon, Cog6ToothIcon, UserCircleIcon} from "@babeard/svelte-heroicons/mini";
export function load() {
return {
menuSettings: {
menuButtonIcon: UserCircleIcon,
menuItems: [
{title: 'Settings', icon: Cog6ToothIcon, url: '/app/settings', current: false},
{title: 'Sign Out', icon: ArrowLeftOnRectangleIcon, url: '/app/sign-out', current: false},
]
}
}
}
This throws an error:
Error: Data returned from `load` while rendering / is not serializable: Cannot stringify a function (data.menuSettings.menuButtonIcon)
Is there a way to return components from a load() function? And if not, what would be the best way to approach this issue?
I would probably give the icons a key, return said key from the load
function and resolve the component on the page.
const icons = {
'user-circle': UserCircleIcon,
'cog-6-tooth': Cog6ToothIcon,
// ...
}
<svelte:component this={icons[menuSettings.menuButtonIcon]} />
Though I suspect very little actually needs to be determined on the server. Usually it's just determining visibility, so you probably can leave much more on the page itself.