
How To Pass Data From Layout Page To descendant pages and components In SvelteKit
April 2nd, 2022
Overview
In the previous article, we went over how to create a standalone endpoint and fetch data from it in a layout and its descendant page. We specifically used a loading input stuff to access the fetched data.
But there are other ways to pass data around in SvelteKit and we will go over them in this article. In order for this article to be comprehensive, I will breifly go over stuff again:
- Context
- Stuff
- Direct import
Getting Started
Terminalnpm init svelte@next sveltekit-tutorialcd sveltekit-tutorialvim .npm installnpm run dev

1. Context
In Svelte and SvelteKit, any components can communicate with each other using Context API. By using it, you don't need to pass data and functions as props, or creating a lot of events to make pages and components to talk to each other.
Let's create __layout.svelte to work on our first example:
In the following layout page, we set context with a parent object.
./src/__layout.svelte1<script>2 import { setContext } from "svelte";34 const parent = { name: "John", email: "john@example.com" };56 setContext("parent", parent);7</script>89<h1>Parent</h1>1011<slot />
Here we simpley import our grandchild component.
./src/index.svelte1<script>2 import Grandchild from "$lib/Grandchild.svelte";3</script>45<h2>Child</h2>67<Grandchild />
In this grandchild component, we use getContext() to access parent.
./src/lib/Grandchild.svelte1<script>2 import { getContext } from "svelte";34 const parent = getContext("parent");5</script>67<h3>Grand Child</h3>89<pre>{JSON.stringify(parent)}</pre>
Make sure to spin up dev server and access http://localhost:3000 in a browser:

2. Stuff
In SvelteKit, the load function receives the following six objects as the function arguments:
urlparamspropsfetchsessionstuff
We are particularly interested in stuff.
In this layout page, we hard-code a parent object having a name and an email properties and attach it to the stuff. This stuff will be available to any subsequent load functions in the descendant layouts and pages.
./src/__layout.svelte1<script context="module">2 export const load = () => {3 const parent = { name: "John", email: "john@example.com" };45 return {6 props: {},7 stuff: {8 parent,9 },10 };11 };12</script>1314<h1>Parent</h1>1516<slot />
To be able to access stuff in a descendant page, we need to use load() and stuff to extract the parent object and attach it to props. Then we export parent as a variable in the second <script> tag:
./src/index.svelte1<script context="module">2 export async function load({ stuff }) {3 const { parent } = stuff;45 return {6 props: {7 parent,8 },9 };10 }11</script>1213<script>14 import Grandchild from "$lib/Grandchild.svelte";15 export let parent;16</script>1718<h2>Child</h2>1920<pre>{JSON.stringify(parent)}</pre>2122<Grandchild />
./src/lib/Grandchild.svelte1<h3>Grand Child</h3>
Make sure to spin up dev server and access http://localhost:3000 in a browser:

Using page intead of load() to access stuff
stuff is also available to pages, components using the page stores. Here is how you do it.
Change index.svelte while __layout.svelte, Grandchild.svelte kept same as above:
./src/routes/index.svelte1<script>2 import { page } from "$app/stores";3 import Grandchild from "$lib/Grandchild.svelte";45 export const { parent } = $page.stuff;6</script>78<h2>Child</h2>910<pre>{JSON.stringify(parent)}</pre>1112<Grandchild />
Make sure to spin up dev server and access http://localhost:3000 in a browser:

3. Direct Import
What if you want to access props, stuff in a grandchild component directly? Remember that we can't use load() mainly because it is available to be used in pages and layouts only, not in components. Then you can simply use a direct import in a component to access data. That is to import load from the layout page and call it as a function in a component.
Now let's go over how we can directly import data from __layout.svelte to Grandchild.svelte component.
./src/routes/__layout.svelte1<script context="module">2 export const parent = { name: "John", email: "john@example.com" };34 export const load = () => {5 return {6 props: {7 foo: "bar",8 },9 stuff: {10 parent,11 },12 };13 };14</script>1516<h1>Parent</h1>1718<slot />
In index.svelte, we simply use load() and stuff to access data from the layout page.
./src/routes/index.svelte1<script context="module">2 export async function load({ stuff }) {3 const { parent } = stuff;45 return {6 props: {7 parent,8 },9 };10 }11</script>1213<script>14 import Grandchild from "$lib/Grandchild.svelte";15 export let parent;16</script>1718<h2>Child</h2>1920<pre>{JSON.stringify(parent)}</pre>2122<Grandchild />
In a grandchild component, instead of using load and stuff that are not available for components, you can import data and load function from the layout page and call it inside a component.
./src/lib/Grandchild.svelte1<script>2 // import parent, load directly from the layout page3 import { parent, load } from "../routes/__layout.svelte";4</script>56<h3>Grand Child</h3>78// Use parent and call load() directly to access data9<pre>parent:{JSON.stringify(parent)}</pre>10<pre>props:{JSON.stringify(load().props)}</pre>11<pre>props:{JSON.stringify(load().stuff)}</pre>
Make sure to spin up dev server and access http://localhost:3000 in a browser:

Comments