How SvelteKit makes type-safe data fetching easier and better!
Tags: webdev, javascript, svelte, tutorial
Published: 2023-01-24 15:47:11

## Introduction
It’s been around a month since SvelteKit v1 was released and I fortunately got enough time to play around with it. In this blog post, I would be writing about the data fetching/loading ways in SvelteKit and how SvelteKit makes it easier along with providing type-safety all the way!

## Creating a new SvelteKit app
Let’s start from the basics in case you know nothing about Svelte. I’ll be creating a new SvelteKit app first. You can use this command to do it as well (make sure you opt-in to use typescript when prompted) -

```bash
pnpm create svelte@latest // or npm create svelte@latest
```

Now that we have our project setup, let’s build a new page. SvelteKit uses a file-based routing just like other frameworks like Next.js. Head over to `src/routes/+page.svelte` in your app. This is the starting point of any SvelteKit app - the Index page. I won’t be creating any more routes as we don’t need them for this blog post. You can learn more about routing from [SvelteKit docs](https://kit.svelte.dev/docs/routing). Start the dev server for the app and if you did everything correctly you should be seeing a page like this if you head over to [localhost:5173](http://localhost:5173). 

![SvelteKit default index page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8w9xb2wm1hfnnv6tfaj.png)

## Understanding data loading in SvelteKit
Now let’s start with the actual topic of this blog post - data fetching. If you read the [SvelteKit docs for data fetching](https://kit.svelte.dev/docs/load), it states that you need separate files for loading your data which can be created for every route  - “A `+page.svelte`file can have a sibling `+page.js`(or `+page.ts`) that exports a `load`function, the return value of which is available to the page via the `data` prop”. Didn’t get it? don’t worry, let’s break it into parts.

So, first of all for every route that you want to load/fetch external data, you need a separate file. For example, for every `+page.svelte` in your routes where you need external data, you will need a corresponding `+page.ts` file for loading its data. The second part says something about a `load`function. A load function is the function that you export from your `+page.ts` file returning the loaded data. SvelteKit autogenerates the return types for you which can be imported in your component file using `$types` module. I think it might be making some sense at this point, but let’s see this in action.

## Do it yourself
Let’s create a new route `todo` in our app and create `+page.svelte` and `+page.ts` files inside it. I’ll be using [dummyjson](https://dummyjson.com) to mimic an external database.

```tsx
// src/routes/todo/+page.ts

import type { PageLoad } from './$types';

type todo = {
	id: number;
	todo: string;
	completed: boolean;
	userId: number;
}; // todo type for better type safety

type t = {
	todos: todo[];
	total: number;
	skip: number;
	limit: number;
}; // actual json reponse type 

export const load: PageLoad = async () => {
	const r = await fetch('https://dummyjson.com/todos');
	const todos = ((await r.json()) as t).todos; // we only want to send the todo array as props
	return {
		props: {
			todos
		}
	};
};
```

```html
<!-- src/routes/todo/+page.svelte -->

<script lang="ts">
	import type { PageData } from './$types';

	export let data: PageData;
</script>

<h1>Todo List</h1>
{#each data.props.todos as todo (todo.id)}
	<div>
		<p>{todo.todo}</p>
	</div>
{/each}
```

If you copy this code to your editor, you would be able to see some beautiful typescript autocompletion working in here. Let’s try to understand the code.

## Understanding the code
First of all I created a `+page.ts` file inside my `todo` route and created a `load` function of the type `PageLoad` . I have fetched the json response from dummyjson inside the function and returned an array of todos from the response. The type `t` at the beginning is optional and you may not use it but the type `todo` is important if you want end-to-end type-safety (also it’s a good practice to keep all the types in a separate file and import them, instead of cluttering the main file). 

SvelteKit then generates the types for the `load` function which could be used in our `+page.svelte`. In the `src/routes/todo/+page.svelte` , we first need to import the generated types and then export it as `data` . The next part is pretty easy if you already know Svelte syntax, we just need to iterated over the array of list and list them down.

If you do everything correctly and then head over to [localhost:5173/todo](http://localhost:5173), you would be able to see something like this -

![Todo List](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7endfvtz3j0oo4fhiahl.png)

## Fetching data server side
So, our data fetching works perfectly fine. You could experiment a bit more with it if you want. But I’ll head over to the last subtopic of the blog which is loading data server side only. In many cases, you would not want your `load` function to not run client side (because it uses private environment variables, for example, or accesses a database). For such cases, SvelteKit provides another similar way for loading data.

To do so, instead of creating a `+page.ts` , you’ll just have to create a `+page.server.ts` and change the function type a bit like this -

```tsx
// src/routes/todo/+page.server.ts

import type { PageServerLoad } from './$types';

type todo = {
	id: number;
	todo: string;
	completed: boolean;
	userId: number;
}; // todo type for better type safety

type t = {
	todos: todo[];
	total: number;
	skip: number;
	limit: number;
}; // actual json reponse type 

export const load: PageServerLoad = async () => {
	const r = await fetch('https://dummyjson.com/todos');
	const todos = ((await r.json()) as t).todos; // we only want to send the todo array as props
	return {
		props: {
			todos
		}
	};
};
```

## Conclusion
You can learn more about the `PageLoad` and `PageServerLoad` types from the [docs](https://kit.svelte.dev/docs/load). If you are new to Svelte and SvelteKit, this might have been a bit harder to understand (maybe) or maybe even some of you wouldn’t like this way of loading data (why do we need to create separate files????). But, believe me, once you start using it, it just becomes natural as your app just gets more organized and I don’t think it’s that bad considering the type-safety you get along with it without using any third party library. 

This is it for this blog post, I hope I was able to explain the topic properly. In case you don’t understand something or think something’s not right, feel free to send a comment my way! 

Thanks a lot for reading!