Erkunde Server Components, das Lesen von Promises mit use und die optimistischen Updates von React 19.
Diese Lektion in Kodokon öffnenReact Server Components (RSC) zeichnen die Grenze zwischen Client und Server neu. Eine Server-Komponente läuft nur auf dem Server: Ihr Code gelangt nie ins Client-Bundle, sie kann async sein, direkt die Datenbank oder das Dateisystem lesen, und ihre Ausgabe wird als serialisierter Stream (das RSC-Payload) an den Browser gesendet, das React mit dem Client-Baum zusammenführt. Im Gegenzug hat sie keinen State, keine Effekte und keinen Zugriff auf den Browser: kein useState, kein useEffect, keine Event-Handler. Sie rendert auf dem Client nie erneut.
// Server component: never sent to the client.
export default async function NotesPage() {
const notes = await db.notes.findAll();
return (
<ul>
{notes.map((note) => (
<li key={note.id}>{note.title}</li>
))}
</ul>
);
}Die Interaktivität lebt in Client-Komponenten, gekennzeichnet durch die Direktive 'use client' am Anfang der Datei. Diese Direktive markiert nicht „eine Client-Komponente“, sondern eine Grenze: Alles, was dieses Modul importiert, wandert ebenfalls auf die Client-Seite. Props, die die Grenze überschreiten, müssen serialisierbar sein: einfache Objekte, Arrays, Promises... aber niemals gewöhnliche Funktionen oder Klasseninstanzen.
'use client';
import { useState } from 'react';
export function LikeButton({ initialCount }) {
const [count, setCount] = useState(initialCount);
return (
<button onClick={() => setCount(count + 1)}>
{count} likes
</button>
);
}React 19 führt use ein, eine API, die den Wert eines Promise oder eines Kontexts liest. Anders als Hooks kann use innerhalb einer Bedingung oder einer Schleife aufgerufen werden. Bei einem Promise suspendiert es die Komponente bis zur Auflösung und stützt sich dabei auf die nächste Suspense-Grenze. Das idiomatische Muster: Eine Server-Komponente erzeugt das Promise, ohne es abzuwarten, gibt es als Prop weiter, und eine Client-Komponente konsumiert es mit use: Der Server beginnt, die Seite zu streamen, ohne auf die Daten zu warten.
import { use, Suspense } from 'react';
function Comments({ commentsPromise }) {
const comments = use(commentsPromise);
return comments.map((c) => (
<p key={c.id}>{c.text}</p>
));
}
function Page({ commentsPromise }) {
return (
<Suspense fallback={<Spinner />}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
);
}Auf der Interaktionsseite markiert useTransition ein Update als nicht dringend und stellt isPending bereit, damit du einen dezenten Indikator zeigen kannst, ohne die Eingabe zu blockieren. useOptimistic vervollständigt das Duo für Netzwerk-Mutationen: Du zeigst sofort den erhofften Zustand an, während eine asynchrone Action läuft; wenn die Action endet (Erfolg oder Fehlschlag), verwirft React den optimistischen Wert und zeigt wieder den echten Zustand, den aus der Source of Truth.
const [optimisticLikes, addOptimisticLike] =
useOptimistic(likes, (count, delta) => count + delta);
function handleLike() {
startTransition(async () => {
addOptimisticLike(1);
await saveLike();
// At the end, React shows the real state again.
});
}use-API brechen?useOptimistic-Wert, wenn die asynchrone Action endet?