Vad vi bygger
En gästbok: ett formulär i React skickar ett meddelande till din server, servern sparar det och visar det för varje framtida besökare. Minns formuläret från nivå 2 som inte hade någonstans att skicka något? Idag betalar vi den skulden.
Jag visar: gästbokens backend
I mappen my-server, installera först ett paket till:
npm install cors
Och redigera server.js:
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors()); // allow the frontend on a different port to ask questions
app.use(express.json()); // understand JSON in incoming requests
const messages = [
{ name: "Martin", text: "First message! Long live the guestbook. 📖" },
];
// GET – hand out messages
app.get("/api/messages", (request, response) => {
response.json(messages);
});
// POST – accept a new message
app.post("/api/messages", (request, response) => {
const { name, text } = request.body;
// Never trust input: check it on the server too!
if (!name || !text || name.length > 50 || text.length > 500) {
return response.status(400).json({ error: "Invalid message." });
}
messages.push({ name, text });
response.json({ saved: true });
});
app.listen(3900, () => {
console.log("Server running at http://localhost:3900");
});
Nytt:
cors()– frontend kör på port 3901, servern på 3900. Webbläsare blockerar normalt “cross-origin”-förfrågningar så här (en säkerhetsregel som heter CORS); så tillåter du det på servern.app.post(...)– ditt första POST-endpoint! Formulärdata dyker upp irequest.body.- Kontroll på servern – frontend kollar redan formuläret, men en angripare kan kringgå formuläret och skicka en förfrågan direkt. Därför gäller järnregeln: backend kollar alltid och litar aldrig på frontend.
status(400)betyder “felaktig förfrågan.”
Jag visar: gästbokens frontend
I ditt React-projekt, skapa src/GuestBook.jsx:
import { useState, useEffect } from 'react';
function GuestBook() {
const [messages, setMessages] = useState([]);
const [name, setName] = useState("");
const [text, setText] = useState("");
// On first render: download the messages from the server
useEffect(() => {
fetch("http://localhost:3900/api/messages")
.then((response) => response.json())
.then((data) => setMessages(data));
}, []);
function submit(event) {
event.preventDefault();
fetch("http://localhost:3900/api/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, text }),
})
.then((response) => response.json())
.then(() => {
setMessages([...messages, { name, text }]); // add it to the screen too
setName("");
setText("");
});
}
return (
<div>
<h2>Guestbook 📖</h2>
{messages.map((message, index) => (
<div className="card" key={index}>
<strong>{message.name}</strong>
<p>{message.text}</p>
</div>
))}
<form onSubmit={submit}>
<input
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Your name"
/>
<textarea
value={text}
onChange={(event) => setText(event.target.value)}
placeholder="Write a message..."
/>
<button type="submit">Send</button>
</form>
</div>
);
}
export default GuestBook;
Tre sista nya saker i React:
useEffect(() => {...}, [])– “kör det här en gång, när komponenten visas första gången.” Den perfekta platsen för att ladda ner data.fetchmedmethod: "POST"– vi skickar data;JSON.stringifypackar den till JSON.- Kopplade formulär – fältet läser sitt värde från state (
value={name}) och skriver tillbaka medan du skriver (onChange). Formuläret och statet hålls alltid synkade.
Nu är det din tur 💪
- Få båda att köra: servern i en terminal (
node server.js), React i den andra (npm run dev -- --port 3901). Två terminaler, två program – välkommen till full-stack! - Lägg till
<GuestBook />i din app och prova: skriv ett meddelande, ladda om sidan – meddelandet finns kvar (så länge servern kör). - Anpassa gästboken till ditt projekt: 🏫 meddelanden till skolan · 🙋 en anslagstavla för kompisar · 🌍 “vart ska vi?”-tips från besökare · ⚽ rop från fansen.
- Prova skicka ett tomt meddelande – frontend släpper igenom det (den har ingen kontroll), men servern avvisar det. Lägg sedan till en kontroll i frontend också, så formuläret är lika artigt som på nivå 2.
Meddelanden försvinner när servern startar om – de lever bara i en array i minnet. Riktiga applikationer sparar dem i en databas, som överlever allt. Det är det första att lära sig när du avslutat den här nivån – nyckelord: SQLite, PostgreSQL.
Kolla själv: Ett meddelande från formuläret reser till servern, sparas och kommer tillbaka efter sidomladdning. Du byggde precis en full-stack-applikation – frontend, backend, API. Det är precis vad professionella utvecklare gör varje dag.
Det här tar du med dig från lektionen
useEffect(..., [])laddar ner data vid första renderingen;fetchmed POST skickar den.- Säkerhetens järnregel: servern kollar all inmatning, även när frontend kollar också.
- Full-stack = två körande program (3901 + 3900) som pratar med varandra via ett API.
© 2026 Ing. Martin Polak / AlgoRhino · Villkor för innehållsanvändning