=========================== Modern Web Development mit React =========================== Dieses Kapitel beschäftigt sich mit modernen Web-Entwicklungstechnologien, wobei der Fokus auf React und der Kommunikation zwischen Frontend und Backend liegt. Wir betrachten die Grundlagen von React, State-Management, Backend-Technologien sowie typsichere API-Architekturen. .. _React_Allgemein: React Allgemein --------------- React ist eine JavaScript-Bibliothek, mit der man moderne Benutzeroberflächen (UIs) bauen kann. Sie wurde von Facebook (heute Meta) entwickelt und arbeitet mit sogenannten Komponenten – das sind wiederverwendbare Bausteine für die UI. Hauptideen von React: * **Komponentenbasiert**: Die Oberfläche besteht aus kleinen, eigenständigen Teilen (Komponenten). * **Deklarativ**: Man beschreibt, wie die UI aussehen soll – React kümmert sich um das Aktualisieren. * **Virtuelles DOM**: Änderungen an der UI werden erst im Hintergrund geprüft, bevor sie im echten Browser sichtbar werden – das macht React schnell. * **JSX**: Eine besondere Schreibweise, mit der man HTML in JavaScript schreiben kann. Grundkonzepte von React ``````````````````````` 1. **Komponenten (Components)** Komponenten sind die Bausteine in React. Sie können wie Funktionen oder Klassen aussehen: - **Funktionskomponenten**: Heute die übliche, einfachere Form. Sie nutzen sogenannte Hooks. - **Klassenkomponenten**: Früher Standard, mit speziellen Methoden für den Lebenszyklus. 2. **Props (Properties)** Props (kurz für "Properties") sind Daten, die von einer übergeordneten Komponente an eine andere weitergegeben werden: - Sie ändern sich nicht (sind „unveränderlich"). - Damit können Komponenten flexibel angepasst werden. 3. **State (Zustand)** Der State beschreibt den aktuellen Zustand einer Komponente, z. B. ob ein Menü offen oder geschlossen ist: - Wird mit `useState` (bei Funktionen) oder `this.state` (bei Klassen) verwaltet. - Wenn sich der State ändert, wird die Komponente neu gerendert. 4. **Lifecycle (Lebenszyklus)** Jede Komponente durchläuft mehrere Phasen: - **Einfügen (Mounting)**: Komponente wird erstellt und in DOM eingefügt - **Aktualisieren (Updating)**: Komponente wird aktualisiert (durch Props oder State) - **Entfernen (Unmounting)**: Komponente wird aus DOM entfernt In Funktionskomponenten nutzt man dafür den `useEffect`-Hook. 5. **Hooks** Hooks sind spezielle Funktionen für Funktionskomponenten: - **useState**: Zustände verwalten - **useEffect**: Dinge tun wie z. B. Daten laden - **useContext**: Gemeinsame Daten verwenden - **useRef**: Auf DOM-Elemente zugreifen Einfaches Beispiel einer React-Komponente: .. code-block:: jsx function Welcome(props) { return

Hallo, {props.name}

; } export default function App() { return (
); } .. _React_State: React State ----------------------- In modernen React-Anwendungen ist das **State Management** ein zentrales Konzept. Der State (Zustand) beschreibt, wie sich Daten innerhalb einer Komponente im Laufe der Zeit verändern. In dem `react-fullstack`-Projekt wird der State genutzt, um Benutzerinteraktionen, API-Daten und UI-Zustände effizient zu verwalten. Was ist State in React? ````````````````````````` Der State ist ein JavaScript-Objekt, das von einer Komponente verwaltet wird. Änderungen am State führen dazu, dass die Komponente (und ihre Kindkomponenten) neu gerendert werden. Lokaler State (Local State) ``````````````````````````````` - Verwaltet mit: ``useState``, ``useReducer`` - Zweck: Speicherung von Daten innerhalb einer Komponente. - Beispiel: Formularfelder, Modals, UI-Toggles. Globaler State (Global State) ````````````````````````````````` - Verwaltet mit: Context API, Redux, Zustand, Recoil, Jotai etc. - Zweck: Gemeinsame Nutzung von Daten zwischen mehreren Komponenten. - Beispiel: Authentifizierungsstatus, Theme, Benutzerdaten. Server State (Asynchroner Remote State) ````````````````````````````````````````` - Verwaltet mit: SWR, React Query, Apollo Client etc. - Zweck: Synchronisation von UI und Backend-Daten. - Beispiel: API-Antworten, Caching, Hintergrund-Aktualisierung. URL State ``````````` - Verwaltet mit: React Router, Next.js router, window.location - Zweck: Zustand, der in der URL kodiert ist (z. B. Query-Parameter). - Beispiel: Pagination, Filter, Tabs. **Beispiel: Einfache Komponente mit State** .. code-block:: jsx import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return (

Aktueller Wert: {count}

); } In diesem Beispiel wird der State-Wert `count` mit dem React-Hook ``useState`` verwaltet. Mit jedem Klick auf den Button wird der Wert erhöht und die Komponente neu gerendert. State in komplexeren Anwendungen ```````````````````````````````````````````` In größeren Projekten wie `react-fullstack` wird State häufig genutzt, um: - Daten von einer API zu laden und darzustellen - Formulareingaben zu verwalten - UI-Zustände wie Ladeindikatoren oder Fehlermeldungen zu steuern **Beispiel: Laden von Daten mit State** .. code-block:: jsx import React, { useState, useEffect } from "react"; function UserList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { fetch("/api/users") .then((res) => res.json()) .then((data) => { setUsers(data); setLoading(false); }); }, []); if (loading) return
Lade Benutzer...
; return ( ); } Hier wird der State genutzt, um sowohl die geladenen Benutzerdaten als auch den Ladezustand zu verwalten. State-Lifting und globale State-Verwaltung ```````````````````````````````````````````````` Oft müssen mehrere Komponenten auf denselben State zugreifen. In solchen Fällen wird der State nach oben ("lifting state up") in eine gemeinsame Elternkomponente verschoben. Für sehr große Anwendungen kann auch ein globales State-Management-Tool wie Redux oder Context API verwendet werden. **Beispiel: State-Lifting** .. code-block:: jsx function Parent() { const [value, setValue] = useState(""); return ( <> ); } function Input({ value, setValue }) { return setValue(e.target.value)} />; } function Display({ value }) { return
Aktueller Wert: {value}
; } Das State Management ist ein zentrales Element jeder React-Anwendung. Mit Hooks wie ``useState`` und ``useEffect`` lassen sich sowohl einfache als auch komplexe Zustände effizient verwalten. In deinem `react-fullstack`-Projekt sorgt ein durchdachtes State Management für eine reaktive, benutzerfreundliche Oberfläche und eine klare Datenflussstruktur. .. _Hono.js: Hono.js HTTP Server ------------------ Einführung ``````````````````````` Hono ist ein minimalistisches, schnelles und modernes Web-Framework für JavaScript/TypeScript, das auf der Web-Standard-API (wie Fetch API, Request und Response) basiert. Es eignet sich hervorragend für serverlose Plattformen, Edge-Umgebungen sowie klassische Node.js-Anwendungen. Architektur ``````````````````````` Die Architektur von Hono ist bewusst schlank gehalten und orientiert sich stark an der Standard-Webplattform. Die wichtigsten Bestandteile sind: - **Router**: Zum Definieren von Routen mittels HTTP-Methoden (GET, POST, etc.). - **Middleware**: Zur Erweiterung oder Veränderung des Request/Response-Flows. - **Kontext-Objekt (`Context`)**: Bietet einfachen Zugriff auf Request, Response, Parameter und Hilfsfunktionen. - **Kompatibilität**: Unterstützt Edge-Plattformen (Cloudflare Workers, Deno, Bun) sowie Node.js. Funktionen ``````````````````````` - **Routing**: Unterstützt Routen mit Parametern, Wildcards und verschachtelten Gruppen. - **Middleware-Support**: Unterstützt beliebige Middleware für Logging, Authentifizierung, etc. - **Standardisierte API**: Verwendet die native `Request` und `Response` API. - **Edge-Optimierung**: Sehr kleine Bundle-Größe und extrem schnelle Startzeit. - **Typisierung**: Volle TypeScript-Unterstützung. Beispiel: Einfache HTTP-Anwendung `````````````````````````````````````````````` Das folgende Beispiel zeigt eine einfache Hono-Anwendung, die HTTP-Anfragen verarbeitet: .. code-block:: javascript import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => { return c.text('Hallo Welt') }) app.get('/user/:name', (c) => { const name = c.req.param('name') return c.text(`Hallo, ${name}`) }) app.post('/echo', async (c) => { const body = await c.req.text() return c.text(`Du hast gesendet: ${body}`) }) export default app Beispielanwendungen ``````````````````````` Hono eignet sich besonders gut für folgende Szenarien: - **Serverlose APIs**: Bereitstellung von REST-APIs auf Plattformen wie Cloudflare Workers oder Vercel Edge Functions. - **Microservices**: Aufbau kleiner, entkoppelter Services mit minimalem Overhead. - **Prototyping**: Schnelles Erstellen von Prototypen und Testservern. - **Middleware-Plattformen**: Authentifizierungs- und Logging-Dienste auf Basis von Middleware-Ketten. Fazit ``````````````````````` Hono ist eine moderne und leichtgewichtige Alternative zu Frameworks wie Express.js oder Fastify, mit Fokus auf Performance, Standardkonformität und Einsatz in Edge-Umgebungen. Dank der einfachen API und guten TypeScript-Unterstützung eignet sich Hono sowohl für Anfänger als auch für erfahrene Entwickler. .. _Rest_API: Allgemein REST API Architektur --------------------------- REST steht für **Representational State Transfer** und ist ein Architekturstil zur Gestaltung von verteilten Systemen, insbesondere Webanwendungen. REST wurde ursprünglich von Roy Fielding im Rahmen seiner Dissertation definiert und bildet heute die Grundlage für viele moderne Web-APIs. Eine REST-API ermöglicht die strukturierte Kommunikation zwischen Client (z. B. einem React-Frontend) und Server über das HTTP-Protokoll. Ziel von REST ist es, Ressourcen über klar definierte URLs bereitzustellen und deren Zustand mithilfe standardisierter HTTP-Methoden wie ``GET``, ``POST``, ``PUT`` oder ``DELETE`` zu verändern oder abzurufen. REST wird häufig für **CRUD-Operationen** verwendet – also Create (Erstellen), Read (Lesen), Update (Aktualisieren) und Delete (Löschen) von Daten. **Wichtige Merkmale von REST-APIs:** - **Zustandslosigkeit**: Jeder Request enthält alle nötigen Informationen zur Verarbeitung. Der Server speichert keinen Client-Zustand zwischen den Anfragen. - **Klare Ressourcendefinition**: Jede Information (z. B. ein Benutzer, ein Artikel) wird als Ressource dargestellt und ist über eine eindeutige URL erreichbar. - **Verwendung von HTTP-Standards**: HTTP-Methoden, Statuscodes, Header und Caching-Verhalten sind vordefiniert und klar verständlich. - **Trennung von Client und Server**: Der Client kennt nur die API-Schnittstelle, nicht deren interne Implementierung – das erleichtert die Weiterentwicklung beider Seiten. Aufbau einer REST-Anfrage ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Eine typische REST-Request besteht aus mehreren Teilen: - **HTTP-Methode**: Legt fest, welche Aktion durchgeführt wird (z. B. ``GET`` für Abfragen, ``POST`` zum Erstellen). - **Endpunkt (URL)**: Gibt an, welche Ressource angesprochen wird, z. B. ``/api/users/42``. - **Header**: Enthält Metadaten wie ``Content-Type`` oder ``Authorization``. - **Body (optional)**: Transportiert Daten zum Server, z. B. bei POST- oder PUT-Anfragen im JSON-Format. Beispiel – eine POST-Anfrage zum Anlegen eines Benutzers: .. code-block:: http POST /api/users HTTP/1.1 Host: example.com Content-Type: application/json Authorization: Bearer { "name": "Max Mustermann", "email": "max@example.com" } Die Serverantwort (Response) könnte wie folgt aussehen: .. code-block:: http HTTP/1.1 201 Created Content-Type: application/json { "id": 42, "name": "Max Mustermann" } Austauschmechanismus – wie REST funktioniert ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ REST nutzt das HTTP-Protokoll als Transportweg. Der Client (z. B. eine React-App) sendet Anfragen an klar definierte Endpunkte des Servers. Der Server verarbeitet die Anfrage, ruft ggf. Daten aus einer Datenbank ab, und sendet die Antwort zurück. Da REST zustandslos ist, kann jeder Request unabhängig behandelt werden – das ist besonders vorteilhaft für die horizontale Skalierung (z. B. über Load Balancer). Warum eignet sich REST gut für Webanwendungen? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ REST-APIs sind aufgrund folgender Eigenschaften besonders gut für den Einsatz im Web geeignet: - **Skalierbarkeit**: Zustandslosigkeit erlaubt verteilte Architekturen und einfache Lastverteilung. - **Lesbarkeit & Wartbarkeit**: Durch die klare Trennung von Ressourcen und Methoden sind APIs leicht verständlich. - **Kompatibilität**: REST nutzt Standardtechnologien (HTTP, JSON), die auf jeder Plattform verfügbar sind. - **Cachbarkeit**: GET-Anfragen können effizient vom Client oder Proxy zwischengespeichert werden. - **Erweiterbarkeit**: Neue Endpunkte oder Datenfelder können leicht ergänzt werden, ohne bestehende Clients zu brechen. Typische HTTP-Statuscodes in REST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ``200 OK``: Erfolgreiche Anfrage mit Antwortdaten - ``201 Created``: Neue Ressource erfolgreich erstellt - ``204 No Content``: Erfolgreiche Anfrage ohne Rückgabedaten - ``400 Bad Request``: Fehlerhafte Anfrage (z. B. ungültige Daten) - ``401 Unauthorized``: Authentifizierung erforderlich - ``404 Not Found``: Ressource nicht gefunden - ``500 Internal Server Error``: Allgemeiner Serverfehler Zusätzlicher Vorteil: Klare Ressourcenzuordnung ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Ein REST-Endpunkt beschreibt immer eine Ressource. Beispielsweise: - ``GET /products`` → Liste aller Produkte - ``GET /products/123`` → Produkt mit ID 123 - ``POST /products`` → Neues Produkt erstellen - ``PUT /products/123`` → Produkt 123 aktualisieren - ``DELETE /products/123`` → Produkt 123 löschen Diese Struktur ist intuitiv und wird von Entwickler*innen schnell verstanden – unabhängig von Programmiersprache oder Framework. Fazit zu REST ^^^^^^^^^^^^^^^ REST ist ein universeller und leicht verständlicher Ansatz zur API-Entwicklung. In modernen Frontend-Stacks wie React spielt REST eine zentrale Rolle, um Daten mit dem Backend auszutauschen. Durch die Nutzung standardisierter Protokolle, Methoden und Formate ermöglicht REST eine robuste, wartbare und skalierbare Schnittstellenarchitektur – ideal für Webanwendungen jeder Größe. .. _Datenkommunikation: Datenkommunikation zwischen React‑Frontend und Backend ----------------------------------------------------- Eine performante, zuverlässige und gut wartbare Kommunikation zwischen Front‑ und Backend ist das Rückgrat jeder modernen Web‑Anwendung. In React gibt es verschiedene Strategien, HTTP‑Requests zu organisieren, Fehler zu behandeln und Daten zu cachen. Dieser Abschnitt stellt bewährte Vorgehensweisen vor und zeigt anhand von Code‑Beispielen, wie sie im Zusammenspiel mit **Hono** und dem React‑Ökosystem umgesetzt werden können. Warum überhaupt eine eigene „Daten‑Schicht“? .. _tRPC_Typsicherheit: Typsichere APIs mit tRPC ------------------------ **tRPC** ist ein Typescript‑first‑Framework, das Ende‑zu‑Ende‑Typsicherheit bietet, ohne dass ein zusätzliches Schema‑Format (etwa OpenAPI oder GraphQL) gepflegt werden muss. Server‑ und Client‑Code teilen sich dieselben TypeScript‑Definitionen; dadurch entstehen *zero‑cost* Typ‑Garantien und weniger Fehlabgleiche zwischen Front‑ und Backend. .. code-block:: tsx import { createTRPCReact } from '@trpc/react-query' import type { AppRouter } from '../server' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' const trpc = createTRPCReact() const qc = new QueryClient() function Hello() { const { data } = trpc.hello.useQuery({ name: 'Max' }) return

{data}

{/* ⟶ "Hello Max" (typsicher) */} } export default function App() { return ( ) } Literatur ---------- - **React (Offizielle Dokumentation)** https://react.dev/ - **React – Hooks API Reference** https://react.dev/reference/react - **TypeScript (Offizielle Dokumentation)** https://www.typescriptlang.org/docs/ - **Hono (Offizielle Dokumentation)** https://hono.dev/docs - **tRPC (Offizielle Dokumentation)** https://trpc.io/docs - **TanStack Router** https://tanstack.com/router/latest/docs/framework/react - **TanStack Query** https://tanstack.com/query/latest/docs/framework/react - **Docker – Get Started** https://docs.docker.com/get-started/ - **PostgreSQL Dokumentation** https://www.postgresql.org/docs/ - **pnpm (Schneller Paketmanager)** https://pnpm.io/ - **Vite (Build Tool für moderne Webprojekte)** https://vitejs.dev/guide/