Accessing URL params in Sapper
Coming from the vue-router domain, I’ve never had trouble accessing the dynamic URL routes in any component.
However, it’s a bit different in Sapper.
The docs are nice, but didn’t fix the issue I have had.
I learnt this the hard way. It was only after hours of failed attempts that I was able to figure it out, how exactly URL params work in Sapper. And more importantly, a big idea about how Svelte is different in this aspect.
In Nuxt.js (or Quasar, or anything that essentially uses vue-router), we can
access the dynamic URL parameters from the component in the following way
(assuming that we have “/greet/:username” registered in vue-router’s path
or
children
):
<!--
For example, this file is
- "/pages/greet/_username.vue" for Nuxt.js
- "src/pages/greet/_username.vue" for Quasar framework
-->
<template>
<div>
<h2>
Hello, {{ $route.params.username }}!
Hope you're doing great.
</h2>
</div>
</template>
To obtain this functionality in Sapper, we use the [slug].svelte
naming
style.
To create a route whose dynamic part is to be called username
in the
component, the file must be named:
/pages/greet/_username.vue
in (say) Nuxt.js/src/routes/[username].svelte
in Sapper.
I wish there was an easy way to access the value of username
in component,
but it’s a bit more unintuitive than I expected.
Accessing the parameter
<!-- This is /src/routes/[username].svelte -->
<script context="module">
export async function preload ({ params, query }) {
return { username: params.username }
}
</script>
<!-- Regular Svelte below. The parameter must be first extracted from the
argument to preload(), and then returned to be made available in a regular
Svelte component.
-->
<script>
export let username;
</script>
<h3>Hey, { username }!</h3>
<p>Hope you're doing great!</p>
Creating the first <script>
should be done in module context. Not doing so
will result in having two <script>
tags, which is against writing Svelte
components. Also, wrapping both exports in a single script renders the value
undefined
without errors.
Based on what I get from the docs, I speculate that its because preload()
executes when the module initializes, which is before the component renders.
So, username
gets populated once the module has rendered. The (later)
initialized component can then access it to display a nice greeting.