Search code examples
sveltesveltekit

How to use reactive statements to fetch data from a +server.js handler in SvelteKit?


I am trying to fetch data from a +server.js handler like this:

<script>
  let subject = "Svelte";

  let message = "";

  // Why does this produce an error?
  $: fetch(`/api/?subject=${subject}`)
    .then((response) => response.json())
    .then((data) => (message = data.message));
</script>

<input bind:value={subject} />

{message}

but I receive this error:

Error: Cannot call fetch eagerly during server side rendering with relative URL (/api/?subject=Svelte) — put your fetch calls inside onMount or a load function instead

I modeled that page after this REPL example which does work, but uses an absolute URL to a remote endpoint. I need to fetch data from a +server.js endpoint.

I don't think the +server.js code matters in this case, but here it is just in case:

import { json } from '@sveltejs/kit';

export async function GET({ url }) {
  const subject = url.searchParams.get("subject");
  return json({ message: `Hello, ${subject}!` });
}

According to the error message, I must put the fetch call inside onMount or a load function.

Putting the code inside onMount eliminates the error, but the fetch is not reactive. Instead, the fetch only executes once and never updates. In addition, I get the following warning:

$: has no effect outside of the top-level

So if fetch calls must be inside onMount or load, and $ must be top-level, how do I fetch data from the +server.js endpoint in a reactive way?

I create a GitHub repository with the reproducible example.


Solution

  • You can do it onMount as suggested, then also bind to the input event on the input which can call your fetch again. Repl here: https://svelte.dev/repl/7c31ebd09e95420385e3c94385a4fb1e?version=3.59.1

    Edit: You could also do this:

    $: if (browser) fetch(/api/?subject=${subject})