Was wir bauen
Ein Gästebuch: Ein Formular in React schickt eine Nachricht an deinen Server, der Server speichert sie und zeigt sie jedem künftigen Besucher. Erinnerst du dich an das Formular aus Level 2, das nirgends etwas hinschicken konnte? Heute zahlen wir diese Schuld ab.
Zeig mir das: das Gästebuch-Backend
Im Ordner my-server zuerst ein Paket mehr installieren:
npm install cors
Und server.js bearbeiten:
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");
});
Neues:
cors()– das Frontend läuft auf Port 3901, der Server auf 3900. Browser blockieren normalerweise solche „Cross-Origin”-Anfragen (Sicherheitsregel CORS); so erlaubst du es auf dem Server.app.post(...)– dein erster POST-Endpoint! Formulardaten stehen inrequest.body.- Prüfung auf dem Server – das Frontend prüft das Formular schon, aber ein Angreifer kann das Formular umgehen und direkt eine Anfrage schicken. Deshalb gilt die eiserne Regel: Das Backend prüft immer und vertraut dem Frontend nie.
status(400)heißt „bad request”.
Zeig mir das: das Gästebuch-Frontend
In deinem React-Projekt erstelle 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;
Drei letzte Neuigkeiten in React:
useEffect(() => {...}, [])– „führe das einmal aus, wenn die Komponente zum ersten Mal erscheint.” Der ideale Ort, um Daten herunterzuladen.fetchmitmethod: "POST"– wir senden Daten;JSON.stringifypackt sie in JSON.- Verbundene Formulare – das Feld liest seinen Wert aus dem State (
value={name}) und schreibt beim Tippen zurück (onChange). Formular und State bleiben immer synchron.
Jetzt du 💪
- Bringe beides zum Laufen: Server in einem Terminal (
node server.js), React im anderen (npm run dev -- --port 3901). Zwei Terminals, zwei Programme – willkommen im Full-Stack! - Füge
<GuestBook />in deine App ein und probiere es: Schreib eine Nachricht, lade die Seite neu – die Nachricht ist noch da (solange der Server läuft). - Passe das Gästebuch an dein Projekt an: 🏫 Nachrichten für die Schule · 🙋 Pinnwand für Freunde · 🌍 „Wohin sollen wir?” Tipps von Besuchern · ⚽ Sprechchöre der Fans.
- Versuche, eine leere Nachricht zu senden – das Frontend lässt sie durch (es prüft nicht), aber der Server lehnt ab. Füge dann auch im Frontend eine Prüfung hinzu, damit das Formular so höflich ist wie in Level 2.
Nachrichten verschwinden beim Server-Neustart – sie leben nur in einem Array im Speicher. Echte Anwendungen speichern sie in einer Datenbank, die alles überlebt. Das ist das Erste, was du nach diesem Level lernen kannst – Stichworte: SQLite, PostgreSQL.
Kontrolliere dich selbst: Eine Nachricht vom Formular geht zum Server, wird gespeichert und kommt nach dem Neuladen zurück. Du hast gerade eine Full-Stack-Anwendung gebaut – Frontend, Backend, API. Genau das machen professionelle Entwickler jeden Tag.
Das nimmst du aus dieser Lektion mit
useEffect(..., [])lädt Daten beim ersten Render;fetchmit POST sendet sie.- Die eiserne Sicherheitsregel: Der Server prüft jede Eingabe, auch wenn das Frontend prüft.
- Full-Stack = zwei laufende Programme (3901 + 3900), die über eine API miteinander reden.
© 2026 Ing. Martin Polak / AlgoRhino · Nutzungsbedingungen für Inhalte