Hva vi bygger
En gjestebok: en formular i React sender en melding til din server, serveren lagrer den og viser den til hver fremtideg besøkende. Husker du formularen fra nivå 2, der ingen steder at sende noe havde? I dag betaler vi den gæld.
Jeg viser deg: gjesteboks-backenden
I mappen my-server, installer først én pakke mere:
npm install cors
Og rediger 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");
});
Nye ting:
cors()– frontend kjører på port 3901, serveren på 3900. Nettlesere blokerer normalt “cross-origin”-forespørgsler som denne (en sikkerhedsregel kalt CORS); sådan tillader du det på serveren.app.post(...)– ditt første POST-endpoint! Formulardata vises irequest.body.- Sjekk på serveren – frontend sjekker allerede formularen, men en angriber kan omgå formularen og sende en forespørgsel direkte. Derfor gjelder jernreglen: backenden sjekker altid og stoler aldrig på frontend.
status(400)betyder “bad request.”
Jeg viser deg: gjesteboks-frontenden
I ditt React-projekt, opprett 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 siste nye ting i React:
useEffect(() => {...}, [])– “kjør dette én gang, når komponenten først vises.” Det ideelle sted at downloade data.fetchmedmethod: "POST"– vi sender data;JSON.stringifypakker det ind i JSON.- Forbundne formularer – feltet leser sin værdi fra state (
value={name}) og skriver den tilbake mens du skriver (onChange). Formularen og staten forblir altid synkroniserede.
Nå er det din tur 💪
- Få begge til at kjøre: serveren i én terminal (
node server.js), React i den anden (npm run dev -- --port 3901). To terminaler, to programmer – velkommen til full-stack! - Legg til
<GuestBook />til din app og prøv det: skriv en melding, genindles siden – meldingen er fortsatt der (så længe serveren kjører). - Tilpas gjesteboken til prosjektet ditt: 🏫 meldinger til skolen · 🙋 en meldingtavle til venner · 🌍 “hvor skal vi hen?”-tips fra besøkende · ⚽ sange fra fansene.
- Prøv at sende en tom melding – frontend lader den passere (den har intet tjek), men serveren afviser den. Legg til så et sjekk til frontend også, så formularen er lige så høflig som i nivå 2.
Beskeder forsvinder, når serveren genstartes – de lever kun i et array i minnen. Ekte applikationer lagrer dem i en database, som overlever alt. Det er det første at lære, når du er ferdig med dette nivå – nøgleord: SQLite, PostgreSQL.
Sjekk deg selv: En melding fra formularen rejser til serveren, blir lagret og kommer tilbake etter gjeninnlasting. Du har nettopp bygget en full-stack-applikation – frontend, backend, API. Nøyaktig det, profesjonelle utviklere gjør hver dag.
Dette tar du med deg fra leksjonen
useEffect(..., [])downloader data ved første render;fetchmed POST sender dem.- Jernreglen for sikkerhed: serveren sjekker hvert input, selv når frontend også sjekker.
- Full-stack = to kjørende programmer (3901 + 3900), der taler med hinanden gjennom en API.
© 2026 Ing. Martin Polak / AlgoRhino · Vilkår for innholdsbruk