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 yourfetch
calls insideonMount
or aload
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.
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}
)