Access a URL parameter outside Sapper script module

By

Learn how to access a URL parameter in Sapper outside the preload function by returning it from preload and exposing it as a prop with export let.

~~~

Sapper is deprecated in favor of SvelteKit and receives no security or bug fixes. Do not use this code in a new project.

To use a URL parameter outside the <script context="module"> block in Sapper, return it from preload(). Whatever preload() returns becomes a prop of the component, which you declare with export let.

Let’s see the full picture.

Suppose you’re building a Svelte application using Sapper, and you have a dynamic page route, for example /routes/[id].svelte.

You want to get the dynamic part of the URL (the id in this case), and you know you can get it in the preload() function in the <script context="module"> part of the component:

<script context="module">
	export async function preload({ params }) {
		const { id } = params
	}
</script>

But the problem is that you need to use it outside of preload(), to perform something else.

Why can’t you just read it from the other script block?

The <script context="module"> block runs before the component is created. It’s a separate scope. Variables defined there in preload() are not visible to the regular <script> block, where your component logic lives.

Sapper gives us a bridge between the two: the return value of preload(). Anything you return from that function is passed to the component as a prop.

The solution

Return the value from preload, and define it as a prop of the component, using the usual export let syntax.

Here’s an example:

<script context="module">
	export async function preload({ params }) {
		const { id } = params
		return { id }
	}
</script>

<script>
export let id

if (typeof window !== 'undefined') {
  alert(id)
}
</script>

Now id is a regular component variable. You can use it in the template, pass it to functions, or fetch data with it.

Notice the typeof window !== 'undefined' check. Sapper renders pages on the server first, and alert() (like the rest of the DOM API) does not exist there. Without the guard, the server render crashes. You only need this check for browser-only code. Using id in the template needs no guard.

A pitfall to watch for

If id shows up as undefined in the component, the usual cause is a missing return. Extracting the param inside preload() is not enough:

export async function preload({ params }) {
	const { id } = params
	// forgot: return { id }
}

No return, no prop. The export let id declaration still exists, but nothing fills it. Add the return { id } line and the value flows through.

One last note: Sapper was later retired in favor of SvelteKit, so this applies to existing Sapper codebases. The idea survived though. In SvelteKit, a load function returns data and the page picks it up, following the same pattern.

Tagged: Svelte · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about svelte: