How to use get parameter on sveltekit when use adapter-static?
Asked Answered
C

5

8

I get error message this when build.

Cannot access url.searchParams on a page with prerendering enabled

How to load and use get parameter?

svelte.config.js

import adapter from '@sveltejs/adapter-static';
import preprocess from 'svelte-preprocess';

const config = {
      preprocess: preprocess({
      }),
    kit: {
        adapter: adapter({
                  pages: 'build',
                  assets: 'build',
                  fallback: null,
                  precompress: false
            }),
            prerender: {
                  default: true
            },
            trailingSlash: 'always'
    }
};

export default config;

qna.svelte

...
import {page} from '$app/stores';
const id = $page.url.searchParams.get('id');
...
Cletacleti answered 2/5, 2022 at 1:59 Comment(0)
P
6

You cannot use the searchParams and have a prerendered site at the same time. There would be potentially infinite variants of your searchParams, so you would have to prerender an infinte number of pages.

If you want a dynamic site, do not prerender that page. You can mark individual pages for not prerendering

<script context="module">
    export const prerender = false;
</script>

Note that now you will need a fallback page and have to make sure to redirect these pages to the index.html otherwise you will get 404s

Proceleusmatic answered 2/5, 2022 at 8:49 Comment(3)
This is not true. You can still fetch dynamic content in for instance onMount on a prerendered page. See "When not to prerender" under kit.svelte.dev/docs/page-options#prerenderEyeful
yes, you can fetch dynamic content on a prerendered in onMount, but this makes this part not prerendered.Proceleusmatic
True. But can still be benefitial to combine the too, depending on the page. You can get the best of to world's with shorter load times, SEO etc but also allow some custom content.Eyeful
B
6

Let me expand on some other answers: url.searchParams can be used with prerended Sveltekit pages, but not on the server side (since their isn't any for prerendered pages)

You can however use url.searchParams in onMount or in constructs like:

 import {browser} from "$app/environment";
 const searchParams = browser && $page.url.searchParams
 
 if (searchParams && searchParams.get("myParam")) console.log("myParam is: ",myParam)

Note the imported browser variable which is true if the code is run on the client side in the browser.

For more details, see https://kit.svelte.dev/docs/page-options#prerender

Burrstone answered 8/3, 2023 at 6:51 Comment(1)
Good point! Rewrote it to reflect this and made it bit more polite too :-)Eyeful
G
3

You actually can use searchParams using adapter-static, but have to follow one rule. Any access to the searchParams has to be done in the Svelte onMount function.

Don't forget to handle the case where no parameter is provided. I think the prerendering won't provide any, so it would otherwise produce an error.

<!-- +page.svelte -->
<script>
    import { page } from '$app/stores';
    import { onMount } from 'svelte';

    let id = '';
    onMount(() => {
        // save the id parameter if it's in the url or an empty string
        id = $page.url.searchParams.get('id') || '';
    });
</script>

{#if id}
    <h2>The id is {id}.</h2>
{:else}
    <h2>No id was provided.</h2>
{/if}
Gerdagerdeen answered 23/8, 2023 at 21:34 Comment(1)
This is explained in the When not to prerender part of the docs.Gerdagerdeen
B
1

You can also use beforeUpdate:

<script>
  let id = null;
  beforeUpdate(() => {
    id =  url.searchParams.get('id');
  });
</script>

<div>
  <!-- Use `id ` -->
</div>

The advantage of beforeUpdate compared to onMount is that it will be re-evaluated when your page changes from /page-path?id=1 and /page-path?id=2, unlike onMount.


For more details on why you cannot use search parameters during prerendering, here is an comment from Rich:

When you prerender, you're writing files to the filesystem so that a simple webserver can serve them. Query parameters can't exist on the filesystem (both in the literal sense that ? isn't an allowed character on all filesystems, and in the sense that the webserver will ignore them), so if you have a prerendered endpoint called /api/posts/get then it doesn't matter how many times you call it with different parameters, it can only be saved as a file once. The files need to have different paths (/api/posts/[slug]), or it won't work.

Brassard answered 15/11, 2023 at 2:39 Comment(0)
E
0

Or you can use the hash-based approach and still have the statically built page check this out https://gist.github.com/woss/afbc7293cc2a6632db585e388ff64583

Elmiraelmo answered 8/2, 2023 at 19:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.