Opens an external site in a new window
Pray for peace.
RODNEY LAB
  • Home
  • Blog
  • Projects
  • Giving
  • Contact

Using fetch with SvelteKit: Call APIs and Server Endpoints # Using fetch with SvelteKit: Call APIs and Server Endpoints #

Using fetch with SvelteKit
  1. Rodney Lab Home
  2. Rodney Lab Blog Posts
  3. SvelteKit Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Using fetch with SvelteKit: Call APIs and Server Endpoints #

Published: 6 months ago
6 minute read Gunning Fog Index: 6.1
Content by Rodney
Author Image: Rodney from Rodney Lab
SHARE:

🖥 The fetch API and SvelteKit #

Using fetch with SvelteKit, you can pull data from your server endpoints ahead of rendering a page or contact external server endpoints from your own server code. As well as that you can contact external server endpoints from client code, perhaps to submit form data or even to get fresh data for refreshing the user interface. In this video we break down those three main use cases and also look at how fetch HTTP requests differ from axios calls. fetch is baked in to SvelteKit so I like to use it in SvelteKit projects.

Hopefully this video will spark some ideas for a new SvelteKit pet project. If that is what you have in mind, listen out for the more in-depth tutorials mentioned in the video. It is my intention that these give you some inspiration, providing launch sites you might base your new projects off. Anyway, I hope this topic is one you will find interesting and look forward to hearing all the questions it generates.

🖥 Using fetch with SvelteKit: Video #

Using fetch with SvelteKit: Call APIs and Server Endpoints

🗳 Poll #

Are you most familiar with using axios, fetch or jQuery.ajax?
Voting reveals latest results.

🖥 Using fetch with SvelteKit: Code #

Frontend: Calling fetch in a SvelteKit Load function #

src/routes/index.svelte
svelte
		
1 <script context="module">
2 export const load = async ({ fetch }) => {
3 try {
4 const response = await fetch('/query/fx-rates.json', {
5 method: 'POST',
6 credentials: 'same-origin',
7 headers: {
8 'Content-Type': 'application/json'
9 },
10 body: JSON.stringify({ currencies: ['CAD', 'GBP', 'IDR', 'INR', 'USD'] })
11 });
12 return {
13 props: { ...(await response.json()) }
14 };
15 } catch (error) {
16 console.error(`Error in load function for /: ${error}`);
17 }
18 };
19 </script>

Calling fetch in a SvelteKit Server Endpoint #

src/routes/query/fx-rates.json.ts
typescript
		
1 import type { Query, QueryLatestArgs } from '$lib/generated/graphql';
2 import type { Request } from '@sveltejs/kit';
3
4 export async function post(
5 request: Request & { body: { currencies: string[] } }
6 ): Promise<{ body: string } | { error: string; status: number }> {
7 try {
8 const { currencies = ['CAD', 'GBP', 'IDR', 'INR', 'USD'] } = request.body;
9
10 const query = `A;
11 query latestQuery(
12 $baseCurrency: String = "EUR"
13 $quoteCurrencies: [String!]
14 ) {
15 latest(
16 baseCurrency: $baseCurrency
17 quoteCurrencies: $quoteCurrencies
18 ) {
19 baseCurrency
20 quoteCurrency
21 date
22 quote
23 }
24 }
25 `;
26
27 const variables: QueryLatestArgs = {
28 baseCurrency: 'EUR',
29 quoteCurrencies: currencies
30 };
31
32 const response = await fetch('https://swop.cx/graphql', {
33 method: 'POST',
34 headers: {
35 'Content-Type': 'application/json',
36 Authorization: `ApiKey ${process.env['SWOP_API_KEY']}`
37 },
38 body: JSON.stringify({
39 query,
40 variables
41 })
42 });
43 const data: { data: Query } = await response.json();
44
45 return {
46 body: JSON.stringify({ ...data })
47 };
48 } catch (err) {
49 const error = `Error in /query/fx-rates.json.ts: ${err}`;
50 console.error(error);
51 return {
52 status: 500,
53 error
54 };
55 }
56 }

Frontend: Using a Svelte Store to Update User Interface with fetch Data #

src/routes/index.svelte
svelte
		
21 <script lang="ts">
22 import '@fontsource/source-sans-pro';
23 import rates from '$lib/shared/stores/rates';
24 import type { Query } from '$lib/generated/graphql';
25 export let data: Query;
26
27 rates.set(data.latest);
28 let newCurrency = '';
29 let submitting = false;
30
31 async function handleSubmit() {
32 try {
33 submitting = true;
34 const response = await fetch('/query/fx-rates.json', {
35 method: 'POST',
36 credentials: 'same-origin',
37 headers: {
38 'Content-Type': 'application/json'
39 },
40 body: JSON.stringify({ currencies: [newCurrency] })
41 });
42 const responseData: { data: Query } = await response.json();
43 const rate = responseData.data.latest[0];
44 submitting = false;
45 rates.set([...$rates, rate]);
46 newCurrency = '';
47 } catch (error) {
48 console.error(`Error in handleSubmit function on /: ${error}`);
49 }
50 }
51 </script>
52
53 <main class="container">
54 <div class="heading">
55 <h1>FX Rates</h1>
56 </div>
57 <ul class="content">
58 {#each $rates as { baseCurrency, quoteCurrency, date, quote }}
59 <li>
60 <h2>{`${baseCurrency}${quoteCurrency}`}</h2>
61 <dl>
62 <dt>
63 {`1 ${baseCurrency}`}
64 </dt>
65 <dd>
66 <span class="rate">
67 {quote.toFixed(2)}
68 {quoteCurrency}
69 </span>
70 <details><summary>More information...</summary>Date: {date}</details>
71 </dd>
72 </dl>
73 </li>
74 {/each}
75 </ul>
76
77 <form on:submit|preventDefault={handleSubmit}>
78 <span class="screen-reader-text"
79 ><label for="additional-currency">Additional Currency</label></span
80 >
81 <input
82 bind:value={newCurrency}
83 required
84 id="additional-currency"
85 placeholder="AUD"
86 title="Add another currency"
87 type="text"
88 />
89 <button type="submit" disabled={submitting}>Add currency</button>
90 </form>
91 </main>

Frontend: Using a Svelte await Block to Update User Interface with fetch Data #

narcissus/demos/narcissus-sveltekit/src/lib/components/PostViewsLikes.svelte
svelte
		
1 <script lang="ts">
2 import website from '$lib/config/website';
3 import PostViewsLikesPure from '$lib/components/PostViewsLikesPure.svelte';
4
5 export let likes: number;
6 export let views: number;
7 export let slug: string;
8 export let comments: number;
9 export let containerClass: string = undefined;
10 export let contentClass: string = undefined;
11 export let interactive: boolean = true;
12
13 const { workerUrl } = website;
14
15 async function getViewsLikes() {
16 try {
17 const url = `${workerUrl}/post/data`;
18 const response = await fetch(url, {
19 method: 'POST',
20 credentials: 'same-origin',
21 headers: {
22 'Content-Type': 'application/json',
23 },
24 body: JSON.stringify({
25 slug,
26 }),
27 });
28 return response.json();
29 } catch (error) {
30 console.error(`Error in getViewsLikes: ${error}`);
31 }
32 }
33
34 const likesPromise = getViewsLikes() ?? { likes, views };
35 </script>
36
37 {#await likesPromise}
38 <PostViewsLikesPure {containerClass} {contentClass} {slug} {likes} {views} {comments} />
39 {:then data}
40 <PostViewsLikesPure
41 {containerClass}
42 {contentClass}
43 {slug}
44 likes={data?.likes ?? likes}
45 views={data?.views ?? views}
46 comments={data?.comments.length ?? comments}
47 {interactive}
48 />
49 {:catch}
50 <PostViewsLikesPure {containerClass} {contentClass} {slug} {likes} {views} {comments} />
51 {/await}

🔗 Using fetch with SvelteKit: Links #

Videos, Tutorials and Sample Code #

  • Complete tutorial on using fetch in SvelteKit code plus using fetch to query a GraphQL API,
  • how to use the fetch PUT method to upload images to cloud storage in SvelteKit and Basic Authorization header construction,
  • using a Svelte store to update the user interface after getting fresh data with fetch,
  • using a Svelte await block to update the user interface after getting fresh data with fetch .

Docs #

  • MDN fetch API docs ,
  • HTTP method docs from MDN ,
  • MDN authorisation header docs ,
  • official Svelte tutorial on await blocks .

Reaching Out #

  • Twitter handle: @askRodney .

🏁 Using fetch with SvelteKit: Summary #

How do you use fetch in SvelteKit client page load functions? #

SvelteKit runs load functions before rendering a client page. That makes them the ideal place to pull in data from your server endpoint in many cases. Although the module which loads functions works differently to typical browser JavaScript blocks, fetch is still available. You can desctructure fetch from the object passed to load function's first argument. Take a look at video for a real-life use case.

How is the fetch API different to using axios? #

It might make sense to use fetch over axios in SvelteKit projects as fetch is already included. That said, there are a few differences, although for the most part, axios and fetch work in the same way. With axios, you can send objects in the data field and they are converted to a string automatically by the package, ready for including in the request. With fetch you just wrap your object in a JSON.stringify() call and it goes in the body field, rather than data. A second difference is in accessing JSON received in a response. With axios the object is accessible via the data field on the resolved promised that is returned by the initial axios call. With fetch you access the data by calling a json() method on the resolved promise. That method call itself returns a new promise, so be sure to let it resolve before attempting to read the embedded JSON.

How do await blocks work in Svelte? #

In Svelte, await blocks are a tidy little way of displaying data recived in a promise. Promises are used when a result cannot be returned immediately. A classic example is fetching data from an external API which is not notmally immediate. The promise is kind of a placeholder returned intially while the requested data is still on its way. The await block in Svelte has three arms. The first it for what you display while you wait for the promise to resolve. You might show a loading indicator or alternatively any available, albeit, stale data. The second arm is used for the content which you want to show once the promise resolves. As you would expect, you can access the promise result here and use it in whatever you render. Finally, we have an optional catch arm. We use this when the promise fails to resolve. You might show a “try again later” message or just the previously available data.

🙏🏽 Feedback #

If you have found this video useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention so I can see what you did. Finally be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.

@askRodney avatar

Rodney

@askRodney

Just put together something on how you can use fetch (included 'for free') in SvelteKit. Fetch lets us

- pull data from server endpoints just before we render pages,
- get data from external API in server endpoints,
- update UI with fresh data (from external API or the server).

pic.twitter.com/vh2UnixbLv

— Rodney (@askRodney) November 22, 2021

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as Search Engine Optimisation among other topics. Also subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

Rodney from Rodney Lab
TAGS:
SVELTEKITCSS

Related Posts

SvelteKit S3 Compatible Storage: Presigned Uploads

SvelteKit S3 Compatible Storage: Presigned Uploads

sveltekit
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Copyright © 2020–2022 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Contact
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.