Kom igång med SvelteKit och Fetch API 🚀
Modulsmål 🎯
Efter denna modul ska du kunna:
- ✅ Sätta upp och köra igång ett SvelteKit-projekt
- ✅ Använda
fetch()
för att hämta data från API:er - ✅ Skicka data till API:er med POST-requests
- ✅ Förstå grunderna i hur klient-server kommunikation fungerar
Du har redan arbetat med Svelte för statiska hemsidor. Nu tar vi steget till SvelteKit - ett fullstack-ramverk som låter oss bygga både frontend och backend! 🌟
Steg 1: Skapa ditt SvelteKit-projekt 🛠️
Setup och första intryck
Din uppgift 1: Skapa projektet och utforska strukturen
# Kör dessa kommandon och observera vad som händer
npm create svelte@latest mitt-sveltekit-projekt
cd mitt-sveltekit-projekt
npm install
npm run dev
Reflektera:
- Vilka filer skapades som du inte sett i vanlig Svelte?
- Vad händer när du besöker
http://localhost:5173
? - Jämför
src/routes/
med en vanlig Svelte-app - vad är skillnaden?
Kom ihåg att alltid vara i rätt mapp när du kör kommandon! Använd cd <mappnamn>
för att navigera och cd ..
för att gå upp en nivå. Kör pwd
(Mac/Linux) eller cd
(Windows) för att se var du är.
Steg 2: Förstå Fetch API:et genom experimentation 🌐
Utforska med ett känt API
Din uppgift 2: Experimentera först med fetch i browser console
Öppna developer tools (F12) och kör detta i console:
// Testa detta i browser console först - vad händer?
fetch('https://jsonplaceholder.typicode.com/posts?_limit=3')
.then(response => /* Vad ska stå här? */)
.then(data => console.log(data));
Frågor att besvara:
- Vad returnerar
fetch()
direkt? - Varför behöver vi
.then()
två gånger? - Vad händer om du tar bort
?_limit=3
?
Första SvelteKit-implementering
Din uppgift 3: Skapa din första fetch i SvelteKit
Ersätt innehållet i src/routes/+page.svelte
:
<script>
import { onMount } from 'svelte';
let posts = [];
let loading = /* Vad ska denna börja med? boolean */;
let error = null;
onMount(async () => {
// Din uppgift: Implementera fetch-logiken här
// 1. Sätt loading till rätt värde
// 2. Fetcha från 'https://jsonplaceholder.typicode.com/posts?_limit=5'
// 3. Hantera response (kommer du ihåg från console-testet?)
// 4. Sätt posts-variabeln
// 5. Hantera fel med try/catch
// 6. Sätt loading till false när klart
try {
// Din kod här
} catch (err) {
// Vad ska hända vid fel?
} finally {
// Vad ska alltid hända?
}
});
</script>
<h1>Mina första API-anrop! 📡</h1>
<!-- Din uppgift: Implementera conditional rendering -->
{#if /* när ska vi visa loading? */}
<p>Laddar data...</p>
{:else if /* när ska vi visa fel? */}
<p class="error">Fel: {error}</p>
{:else}
<div class="posts">
<!-- Din uppgift: Loopa genom posts och visa titel + body -->
<!-- Tips: använd {#each posts as post} -->
</div>
{/if}
<style>
/* Din uppgift: Lägg till styling för .post och .error */
</style>
Frågor för reflektion:
- Varför använder vi
onMount
istället för att fetcha direkt i script? - Vad är skillnaden mellan
let loading = true
ochlet loading = false
? - Varför behöver vi try/catch/finally?
Steg 3: Skicka data med POST - Guided Discovery 📤
Först: Förstå vad POST gör
Din uppgift 4: Experimentera med POST i browser console
// Testa detta först - vad skickar vi?
const newPost = {
title: 'Min titel',
body: 'Mitt innehåll',
userId: 1
};
// Din uppgift: Fyll i de tomma delarna
fetch('https://jsonplaceholder.typicode.com/posts', {
method: /* Vilken HTTP-metod? */,
headers: {
'Content-Type': /* Vilken content-type för JSON? */,
},
body: /* Hur konverterar vi objektet till sträng? */
})
.then(response => response.json())
.then(data => console.log('Skapad:', data));
Implementera i SvelteKit
Din uppgift 5: Lägg till ett formulär för att skapa inlägg
Lägg till detta EFTER ditt befintliga innehåll i +page.svelte
:
<script>
// Befintlig kod här...
// Nya variabler för formuläret - vilka behöver vi?
let newPostTitle = '';
let newPostBody = '';
let isSubmitting = /* börjar vi med att submitta? */;
async function createPost() {
// Din uppgift: Implementera denna funktion
// 1. Validera att titel och body inte är tomma
// 2. Sätt isSubmitting till true
// 3. Skicka POST-request (använd samma struktur som console-testet)
// 4. Om framgång: lägg till det nya inlägget i posts-arrayen
// 5. Rensa formuläret
// 6. Hantera fel
// 7. Sätt isSubmitting till false
// Validering först:
if (/* kontrollera om titel eller body är tomma */) {
alert('Fyll i både titel och innehåll!');
return;
}
// Din implementation här:
}
</script>
<!-- Befintligt innehåll här... -->
<section class="create-post">
<h2>Skapa nytt inlägg ✍️</h2>
<!-- Din uppgift: Skapa formuläret -->
<!-- Tips: använd on:submit|preventDefault för att förhindra page reload -->
<form on:submit|preventDefault={/* vilken funktion? */}>
<div>
<label for="title">Titel:</label>
<!-- Bind input till newPostTitle variabeln -->
<input
id="title"
type="text"
bind:value={/* vilken variabel? */}
placeholder="Skriv en titel..."
disabled={/* när ska input vara disabled? */}
/>
</div>
<div>
<label for="body">Innehåll:</label>
<!-- Samma för textarea -->
<textarea
id="body"
bind:value={/* vilken variabel? */}
placeholder="Skriv ditt inlägg..."
disabled={/* när ska textarea vara disabled? */}
></textarea>
</div>
<!-- Knapp som visar olika text beroende på om vi submittar -->
<button type="submit" disabled={/* när ska knappen vara disabled? */}>
{/* Conditional text: "Skapar..." eller "Skapa inlägg" */}
</button>
</form>
</section>
<style>
/* Befintlig CSS... */
/* Din uppgift: Styling för formuläret */
.create-post {
/* Bakgrund, padding, margin? */
}
.create-post div {
/* Spacing mellan form-element? */
}
.create-post input,
.create-post textarea {
/* Styling för inputs? */
}
.create-post button {
/* Styling för knapp? */
}
.create-post button:disabled {
/* Hur ska disabled knapp se ut? */
}
</style>
Steg 4: Problemlösning och fördjupning 🔧
Vanliga utmaningar - Lös själv först!
Utmaning 1: Command not found
# Om du får detta fel:
npm: command not found
Din uppgift: Vad kan detta bero på? Hur löser du det?
Utmaning 2: Port redan används
# Om du får:
Error: Port 5173 is already in use
Din uppgift: Vad betyder detta? Hitta minst 2 sätt att lösa det.
Utmaning 3: Data visas inte Symtom: Formuläret skickas men inlägget syns inte i listan. Din uppgift: Debug steg för steg:
- Öppna Network tab i developer tools
- Vad visar POST-requesten?
- Logga
newPost
innan du lägger till den i posts - Kontrollera att du uppdaterar posts-arrayen korrekt
Experimentera vidare
Din uppgift 6: Implementera dessa förbättringar själv
-
Delete-funktionalitet
- Lägg till en "Ta bort"-knapp på varje inlägg
- Använd DELETE-request till
https://jsonplaceholder.typicode.com/posts/${id}
- Ta bort inlägget från posts-arrayen
-
Edit-funktionalitet
- Lägg till "Redigera"-knapp
- Visa redigeringsformulär
- Använd PUT-request för att uppdatera
-
Bättre felhantering
- Visa specifika felmeddelanden
- Retry-funktion vid nätverksfel
- Loading state per inlägg
Reflektion: Vilken av dessa var svårast? Varför?
Viktiga koncept att reflektera över 🧠
Async/Await vs Promises
Din uppgift: Skriv om din fetch-kod med .then()
istället för async/await. Vilken föredrar du och varför?
State Management
Frågor att fundera på:
- Varför behöver vi
let posts = []
istället förconst
? - Vad händer om två API-anrop sker samtidigt?
- Hur skulle du hantera konflikter mellan lokal och server-data?
User Experience
Utvärdera din app:
- Hur länge väntar användaren på data?
- Vad händer vid långsamma anslutningar?
- Känns appen responsiv?
Debugging Workshop 🔍
Din uppgift 7: Introduktion av buggar att hitta och fixa
Lägg till dessa buggar i din kod och försök hitta dem:
<script>
// Bug 1: Glöm await
onMount(() => {
fetch('...') // Vad händer utan await?
.then(...)
});
// Bug 2: Fel variabelnamn
let newPostTitle = '';
// Men i formuläret: bind:value={newTitle}
// Bug 3: Glöm finally-block
try {
// fetch...
} catch (err) {
error = err.message;
// Vad händer om loading aldrig sätts till false?
}
</script>
Frågor: Hur upptäcker du varje bug? Vilka verktyg hjälper dig?
Nästa steg och utmaning 🚀
Din uppgift 8: Förbered för nästa modul
I nästa modul ska vi bygga våra egna API-endpoints. Fundera på:
- Vad är skillnaden mellan att använda andras API:er och att bygga egna?
- Vilka fördelar skulle det ge att kontrollera servern själv?
- Vilka nya utmaningar tror du det medför?
Experiment: Hitta ett annat gratis API (t.ex. från denna lista) och implementera det i din app.
Nu förstår du grunderna i klient-server kommunikation. I nästa modul bygger vi server-sidan också!
Sammanfattning av viktiga lärdomar
Efter denna modul bör du förstå:
- SvelteKit-projektstruktur och hur den skiljer sig från vanlig Svelte
- Fetch API för att kommunicera med servrar
- Asynkron programmering med async/await
- State management i Svelte-komponenter
- Felhantering vid nätverksanrop
- Formulärhantering och användarinteraktion
Nästa: Vi bygger våra egna API-endpoints med +server.ts
!