Loading Data

In this module, we will learn how to fetch and manipulate data before rendering the page using the load function.
Table of Contents
Course Version History
  • Nov. 21, 2022 - Updated to SvelteKit v1.0.0-next.549. Changed to the new load function API.

In the last module we learned how to create endpoints and fetch data from them. In the example we created, we fetch product data using the dynamic param, [name], of the page that we are on. While this works, there is a more convenient way to load data into a page using a sibling +page.js file.

A +page.svelte file can have a sibling +page.js (or +page.ts) that exports a load function. The return value of this function is available to the page through the data prop.

Let's create the new file /src/routes/product/[name]/+page.js, which will export a load function like this:

export function load() {}

This will have the same functionality as the endpoint created in the last module, so we will use the dynamic name param to find the product data in an array of products. Similar to our endpoint, the load function has access to dynamic parameters through the parameter params. Let's use this to get our product name like this:

export function load({ params }) {
  const productName = params.name;
}

Now, let's add a hard coded array of products, and use productName to search this array and return the correct product.

export function load({ params }) {
  const productName = params.product;
  const product = products.find((product) => product.name === productName);
  return {
    product,
  };
}

Finally, instead of fetching data from our endpoint in /src/routes/product/[name]/+page.svelte, we can use the data prop like this:

export let data;
let product = data.product;

Here we are exporting our prop, data, making it available to our sibling +page.js file where its value will be assigned. As soon as we route to this page, the load function will automatically be called, and the value of data will be set to the value returned from the load function in +page.js. We can then use this data in +page.svelte!

Testing this out in the browser, you will see the page has the same functionality using much less code!

We will learn more about how the load function works later on in this module .The most important thing to know is that is runs on both the client and the server, unlike endpoints which only run on the server. This means that you should not use any sensitive information here. However, if your load function should always run on the server (because it uses private environment variables, accesses a database, etc.) then you can put it in a +page.server.js instead.

Layouts can also load data through +layout.js or +layout.server.js. It works the exact same way as pages, accessing the returned data through the data prop. Any data returned from layout load functions is also available to child +layout.svelte components and the +page.svelte component in addition to the layout that it belongs to. If multiple load functions return data with the same key, the last one will take priority. For example, if we are using data.product in a page where its layout returns {product: 'T-Shirt'} and the page also returns {product: 'Cup'}, then data.product will be Cup.

At this point we've learned that a +page.svelte component, and each +layout.svelte component above it, has access to its own data as well as all the data from its parents.

In some cases, we might need the opposite — a parent layout might need to access data from a page or a child layout. For example, the root layout might want to access the product property returned from our load function in /src/routes/product/[name]/+page.js. We can do this using $page.data.

In our root layout, let's import page. As we learned in the previous module on stores, we can reference a store value by prefixing the store name with a dollar sign. Let's log $page.data.product like this:

import { page } from '$app/stores';
console.log($page.data.product);

Now, if we navigate to our product page, we see that our product object is logged in our layout!

As we've seen there are two types of load functions. +page.js and +layout.js files export load functions that are shared between server and browser, while +page.server.js and +layout.server.js files export load functions that are server-only. Conceptually, they're the same thing, but there are some key differences.

Both shared and server-only load functions have access to three properties (params, route, and url) and various functions (depends, fetch, and parent).

Server-only load functions are called with a ServerLoadEvent, which inherits clientAddress, cookies, locals, platform, and request from RequestEvent.

Shared load functions are called with a LoadEvent, which has a data property. If you have load functions in both +page.js and +page.server.js, the return value of the server-only load function is the data property of the shared load function's argument.

A shared load function can return an object containing any values, including things like custom classes and component constructors.

A server-only load function must return data that can be serialized with devalue such as anything that can be represented as JSON or things like BigInt, Date, etc. — so that it can be transported over the network.

Now that we know the correct way to load data into our app using the load function, in the next module we will learn how to prefetch our data to make our app feel extra snappy.