Client-Side Pages, Components, and Interactivity

Routing and Dynamic Pages


Learning Objectives

  • You know of SvelteKit’s file-based routing.
  • You know how to create routes with dynamic parameters and you know how to access the parameters.
  • You know of some curveballs that relate to dynamic parameters.

Routing and SvelteKit

Svelte has a framework SvelteKit, which is actually what we’ve been using. SvelteKit is a framework for building web applications with Svelte.

SvelteKit uses file-based routing, where files and folders in the src/routes folder define the routes of the client-side application. As we know, a path /books would correspond to a +page.svelte file in the folder src/routes/books.

Here, we’ll work a bit on dynamic routes. Work on the examples in the walking skeleton. As a starting point, create the folder books into src/routes, and then create a file called +page.svelte in the folder src/routes/books. Place the following content to the file.

<p>books!</p>

Now, when you navigate to the path /books in the application, you should see the text “books!”.

Routes with dynamic parameters

Routes with dynamic parameters are defined by creating a folder where the name is enclosed in square brackets, such as [bookId]. The name inside the brackets is used as the name of the parameter (we’ll look into using the parameter in a moment).

To try this out, create a folder called [bookId] in the src/routes/books folder. In this folder, create a file called +page.svelte, and place the following content to the file.

<p>one book!</p>

Now, when you open up the application and navigate to the path /books/1, you should see the text “one book!”. Similarly, when you access the path /books/5, you should see the text “one book!”.

Loading Exercise...

Accessing dynamic parameters

To access dynamic parameters from the route in the +page.svelte file, we need to provide instructions on how to load the dynamic parameters. In SvelteKit, this is done by exporting a function called load from a file called +page.js. The file +page.js is placed in the same folder as the +page.svelte file.

Create a file called +page.js and place it to the folder src/routes/books/[bookId] (with the +page.svelte that shows the text “one book!”). Place the following content to the file.

export const load = ({ params }) => {
  return params;
};

Now, the +page.svelte file can access the dynamic parameters through a property called data. Properties are accessed using the $props() function, which is a SvelteKit-specific function that provides access to the properties passed to the component.

Modify the src/routes/books/[bookId]/+page.svelte file to the following.

<script>
  let { data } = $props();
</script>

<p>book {data.bookId}</p>

With this in place, when you access the path /books/1, you should see the text “book 1”. Similarly, when you access the path /books/5, you should see the text “book 5”, and so on.

Loading Exercise...

Slight curveballs

There are a few curveballs that relate to dynamic parameters that are good to be aware of.

Components are not recreated when navigating

When navigating to a different route, components are not recreated. Instead, the component is updated with new properties. This can lead to unexpected behavior if you create variables based on the properties, as the variables will not be updated when the properties change.

To try this out, modify the src/routes/books/[bookId]/+page.svelte file to match the following.

<script>
  let { data } = $props();
  let bookId = parseInt(data.bookId);
  let nextBookId = bookId + 1;
</script>

<p>book {data.bookId}</p>

<p>Current book id: {bookId}</p>
<p>Next book id: {nextBookId}</p>

<p><a href="/books/{nextBookId}">Next book</a></p>

When you open up the page in a browser and navigate to the path /books/1, you should see the text “book 1”, “Current book id: 1”, and “Next book id: 2”. However, when you click the “Next book” link, you are taken to the path /books/2, but the text still shows “book 1”, “Current book id: 1”, and “Next book id: 2”.

There are two ways to fix this. One, we can use the data directly without creating new variables.

<script>
  let { data } = $props();
</script>

<p>book {data.bookId}</p>

<p>Current book id: {data.bookId}</p>
<p>Next book id: {parseInt(data.bookId) + 1}</p>

<p><a href="/books/{parseInt(data.bookId) + 1}">Next book</a></p>

And two, we can use a derived rune to create variable that keeps track of changes to data.

<script>
  let { data } = $props();

  let bookId = $derived(parseInt(data.bookId));
  let nextBookId = $derived(bookId + 1);
</script>

<p>book {data.bookId}</p>

<p>Current book id: {bookId}</p>
<p>Next book id: {nextBookId}</p>

<p><a href="/books/{nextBookId}">Next book</a></p>

We’ll look into runes in more detail later in the course.

Loading Exercise...

Parameters and string comparison

Dynamic parameters are strings which can lead to unexpected behavior when comparing the parameters to other data types, such as numbers.

To try this out, modify the src/routes/books/[bookId]/+page.svelte file to the following.

<script>
  let { data } = $props();
</script>

<p>book {data.bookId}</p>
{#if data.bookId === 1}
  <p>book id is number 1</p>
{:else}
  <p>book id is not number 1</p>
{/if}

When you access the path /books/1, you will see the text “book 1” and “book id is not number 1”. This is because the dynamic parameter data.bookId is a string, and the comparison data.bookId === 1 compares a string to a number, which will always return false.

If you need to work with other data types, such as numbers, you can convert the string to the desired data type. The following example uses parseInt to turn the book id to a number.

<script>
  let { data } = $props();
  let bookId = parseInt(data.bookId);
</script>

<p>book {bookId}</p>
{#if bookId === 1}
  <p>book id is number 1</p>
{:else}
  <p>book id is not number 1</p>
{/if}

Now, when you again access the path /books/1, you should see the text “book 1” and “book id is number 1”.

Loading Exercise...

Multiple dynamic parameters

A path can have multiple dynamic parameters, such as /books/1/chapters/2. To try this out, create a folder chapters in the folder src/routes/books/[bookId], and place a folder [chapterId] in it.

In the folder src/routes/books/[bookId]/chapters/[chapterId], create a file called +page.js, and place the following content to the file.

export const load = ({ params }) => {
  return params;
};

Then, create a file called +page.svelte to the same folder, and place the following content to the file.

<script>
  let { data } = $props();
</script>

<p>book {data.bookId}, chapter {data.chapterId}</p>

Now, when you access the path /books/1/chapters/2, you should see the text “book 1, chapter 2”. Similarly, when you access the path /books/5/chapters/3, you should see the text “book 5, chapter 3”. This is shown in Figure 1 below.

Fig 1. -- Dynamic parameters can be used to influence what is shown in the browser. In the figure, the user has navigated to http://localhost:5173/books/1/chapters/2 and sees the text "book 1, chapter 2"

Fig 1. — Dynamic parameters can be used to influence what is shown in the browser. In the figure, the user has navigated to http://localhost:5173/books/1/chapters/2 and sees the text “book 1, chapter 2”
Loading Exercise...

Summary

To summarize:

  • SvelteKit uses file-based routing, where files and folders in the src/routes folder define the routes of the client-side application.
  • Routes with dynamic parameters are defined by creating a folder where the name is enclosed in square brackets, such as [bookId].
  • The name inside the brackets is used as the name of the parameter.
  • Given a +page.js file that exports a load function returning the parameters, dynamic parameters can be accessed in the +page.svelte file through a property called data, which is accessed using the $props() function.
  • When navigating to a different route, components are not recreated. Instead, the component is updated with new properties. This can lead to unexpected behavior if you create variables based on the properties, as the variables will not be updated when the properties change.
  • Dynamic parameters are always strings. If you need to work with other data types, you can convert the string to the desired data type, such as using parseInt to convert a string to a number.
Loading Exercise...