ūüĒ• Join our¬†free ¬†SvelteKit Workshop on June 28 -¬†only 9 seats remaining ! ūüí®¬†Save Your Spot!

State in URL: the SvelteKit approach

Justin's profile pic

Justin Ahinon

Last updated on

Table of Contents

    State in URL: the SvelteKit approach

    Some context

    Last week, while working on a project for the WNBA at my day job, I came across an interesting task. We were building a component that would display some data fetched on the server-side. On the frontend, we would have a dropdown that would allow the user to filter the data by a certain property.

    The data we were fetching was big enough that we didn’t want to fetch it all at once. Instead, we only fetch on page load a part of it, and update the UI every time the user changes the filter.

    We were working with Next.js, so I used  getServerSideProps getServerSideProps  to fetch the data, and some states to keep track of the current filter. To update the data on filter change, I used Next.js router  to push a new URL with the new filter as a query parameter. This triggered a new server-side render, and the component was updated with the new data.

    While working on this component, I was wondering how I could do the same thing with SvelteKit.

    This blog post is a summary of the approach I’d use to build the same component in SvelteKit.

    What I’m going to build

    To illustrate the approach, I’m going to build a simple component that displays a list of countries, and allows the user to filter them by continent.

    I’m using the restcountries  API to get the data.

    Getting the data on the server

    To fetch our data from the server, we're going to use SvelteKit load function. This function is first called on the server on initial page load, and then on the client when navigating to the page.

    I wrote a blog post about load functions in SvelteKit here: https://www.okupter.com/blog/sveltekit-internals-load-function

    Since we need the data returned to be updated every time the user changes the filter, we need to "make it depends " on whatever we trigger on the client when the user changes the filter. In our case, we're going to use the URL query parameters.

    TYPESCRIPT

    If you want to learn more about query parameters in SvelteKit, I also wrote a blog post about it here: https://www.okupter.com/blog/sveltekit-query-parameters

    Our load function is pretty simple. It fetches the data from the API, and returns it as a prop to the component.

    We could have made it a bit more complete by adding some validation in case the user manually enters an invalid region in the URL. Think of something like:

    TYPESCRIPT

    Displaying the data

    Data table

    Since we are returning the data from the server as a prop, we can now display it in our component.

    SVELTE

    Quite straightforward. We just iterate over the list of countries and display them in a table.

    Notice that here, we are not destructuring the  data  prop to use  countries  directly. This is because  data  itself is reactive (whenever it changes on the server, the component will update it). But  const { countries } = data  would not be reactive, and would only be updated on the initial page load.

    Using directly  data.countries  might be a bit verbose, but it spares us from having to create another reactive variable to keep track of the countries.

    The select dropdown

    Now that we have our data displayed, let's add a dropdown to filter the countries by continent. This is where the fun begins.

    SVELTE

    The important part here is the  handleRegionChange  function. It uses the  goto  function from SvelteKit to push a new URL with the new region as a query parameter. This is all we need to trigger a new server-side render, and update the data.

    Now, we can populate the select dropdown with the list of regions we created earlier and bind its value to the  selectedRegion  variable.

    SVELTE

    And that's all we need.

    Now, every time the user changes the region, the server will fetch again the data from the API, and the component will update. The reason why the server can re-fetch the data is because of how SvelteKit handles invalidation. If your load function depends on or references a property whose value has changed, the page will be invalidated, and the load function will be called again.

    Note: Read more about invalidation in SvelteKit here: https://kit.svelte.dev/docs/load#invalidation.

    Conclusion

    I very much like the way SvelteKit makes it easy to handle reactive and stateful data. The approach is clean, simple, and very powerful.

    You might also like these blog posts

    SvelteKit Internals: Load function

    SvelteKit Internals: Load function

    Discover how SvelteKit's load function simplifies data loading in your web app.

    Taking advantage of query parameters in SvelteKit

    Taking advantage of query parameters in SvelteKit

    Master the art of query parameters in SvelteKit! Discover how to access and use them on both the client and server side with clear examples and explanations.