Updated for React 19 — includes Actions, Server Components, React Compiler & neue Hooks.

Komponenten

// Function Component (Standard)
function Greeting({ name, age }) {
  return <h1>Hello, {name}! Age: {age}</h1>;
}

// Arrow Function
const Greeting = ({ name }) => <h1>Hello, {name}!</h1>;

// Default Props
function Button({ label = "Click me", variant = "primary" }) {
  return <button className={variant}>{label}</button>;
}

// Children
function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

Hooks

useState

const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: '', age: 0 });

setCount(5);                     // direkt setzen
setCount(prev => prev + 1);      // basierend auf vorherigem Wert

// Objekte immer neu erstellen (immutable!)
setUser(prev => ({ ...prev, name: 'Max' }));

useEffect

// Nach jedem Render
useEffect(() => { document.title = `Count: ${count}`; });

// Nur beim Mount
useEffect(() => {
  const subscription = subscribe();
  return () => subscription.unsubscribe();   // Cleanup
}, []);

// Wenn sich count ändert
useEffect(() => {
  fetchData(count);
}, [count]);

useRef

const inputRef = useRef(null);
const renderCount = useRef(0);

// DOM-Element referenzieren
<input ref={inputRef} />
inputRef.current.focus();

// Wert speichern ohne Re-Render
renderCount.current++;

useMemo & useCallback

// Teuren Wert cachen (React Compiler macht das oft automatisch!)
const sorted = useMemo(() => items.sort(compareFn), [items]);

// Funktion referenziell stabil halten
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

useReducer

function reducer(state, action) {
  switch (action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'decrement': return { count: state.count - 1 };
    case 'reset':     return { count: 0 };
    default:          throw new Error('Unknown action');
  }
}

const [state, dispatch] = useReducer(reducer, { count: 0 });
dispatch({ type: 'increment' });

React 19: Neue Hooks

useActionState

import { useActionState } from 'react';

// Ersetzt manuelles isLoading/error/success State-Management
async function submitForm(prevState, formData) {
  const name = formData.get('name');
  const result = await saveUser(name);
  return { success: true, message: `Saved ${name}` };
}

function MyForm() {
  const [state, formAction, isPending] = useActionState(submitForm, null);

  return (
    <form action={formAction}>
      <input name="name" />
      <button disabled={isPending}>
        {isPending ? 'Saving...' : 'Save'}
      </button>
      {state?.message && <p>{state.message}</p>}
    </form>
  );
}

useFormStatus

import { useFormStatus } from 'react-dom';

// Muss innerhalb eines <form> gerendert werden!
function SubmitButton() {
  const { pending, data } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

function MyForm() {
  return (
    <form action={handleSubmit}>
      <input name="email" />
      <SubmitButton />           {/* greift auf Form-Status zu */}
    </form>
  );
}

useOptimistic

import { useOptimistic } from 'react';

function TodoList({ todos, addTodo }) {
  const [optimisticTodos, addOptimistic] = useOptimistic(
    todos,
    (currentTodos, newTodo) => [...currentTodos, { ...newTodo, pending: true }]
  );

  async function handleAdd(formData) {
    const newTodo = { text: formData.get('text') };
    addOptimistic(newTodo);        // sofort anzeigen
    await addTodo(newTodo);        // Server-Request
    // Bei Erfolg: todos-Prop aktualisiert → optimistic wird überschrieben
    // Bei Fehler: optimistic wird automatisch zurückgerollt
  }

  return (
    <form action={handleAdd}>
      <input name="text" />
      <button>Add</button>
      {optimisticTodos.map(t => (
        <li style={{ opacity: t.pending ? 0.5 : 1 }}>{t.text}</li>
      ))}
    </form>
  );
}

use()

import { use, Suspense } from 'react';

// Promise lesen — React suspends automatisch
function UserProfile({ userPromise }) {
  const user = use(userPromise);     // kein await nötig!
  return <h1>{user.name}</h1>;
}

// Verwendung mit Suspense
<Suspense fallback={<Spinner />}>
  <UserProfile userPromise={fetchUser(id)} />
</Suspense>

// Context lesen (ersetzt useContext) — kann conditional aufgerufen werden!
function Theme({ isAdmin }) {
  if (isAdmin) {
    const theme = use(ThemeContext);    // conditional erlaubt!
    return <AdminPanel theme={theme} />;
  }
  return <UserPanel />;
}

React 19: Weitere Neuerungen

ref als normaler Prop (kein forwardRef mehr!)

// Vorher
const Input = forwardRef((props, ref) => <input ref={ref} {...props} />);

// Jetzt: ref ist ein ganz normaler Prop
function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

// Ref Cleanup Function
<div ref={(node) => {
  // Setup
  node.addEventListener('click', handler);
  // Cleanup (neu!)
  return () => node.removeEventListener('click', handler);
}} />

Context ohne .Provider

// Vorher
<ThemeContext.Provider value={theme}>
  <App />
</ThemeContext.Provider>

// Jetzt
<ThemeContext value={theme}>
  <App />
</ThemeContext>

Document Metadata

// title, meta, link direkt in Komponenten — React hoisted automatisch zu <head>
function BlogPost({ post }) {
  return (
    <article>
      <title>{post.title}</title>
      <meta name="description" content={post.summary} />
      <link rel="canonical" href={post.url} />
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </article>
  );
}
// Kein react-helmet mehr nötig!

React Compiler (v1.0)

# Installation
npm install -D babel-plugin-react-compiler

# babel.config.js
module.exports = {
  plugins: [
    ['babel-plugin-react-compiler'],    // MUSS als erstes Plugin!
    // ... andere Plugins
  ],
};
// Der Compiler macht automatisch:
// ✅ useMemo für teure Berechnungen
// ✅ useCallback für Event-Handler
// ✅ React.memo für Komponenten

// Du schreibst einfach:
function TodoList({ todos, filter }) {
  const filtered = todos.filter(t => t.status === filter);   // auto-memoized!
  return filtered.map(t => <TodoItem key={t.id} todo={t} />);
}

Conditional Rendering

// &&
{isLoggedIn && <Dashboard />}

// Ternary
{isLoggedIn ? <Dashboard /> : <Login />}

// Early Return
function Page({ user }) {
  if (!user) return <Login />;
  return <Dashboard user={user} />;
}

Listen rendern

{items.map(item => (
  <li key={item.id}>{item.name}</li>
))}

// Mit Index (nur wenn keine stabile ID vorhanden)
{items.map((item, index) => (
  <li key={index}>{item}</li>
))}

// Fragments
{items.map(item => (
  <Fragment key={item.id}>
    <dt>{item.term}</dt>
    <dd>{item.definition}</dd>
  </Fragment>
))}

Event Handling

<button onClick={() => handleClick(id)}>Click</button>
<input onChange={(e) => setName(e.target.value)} />
<form onSubmit={(e) => { e.preventDefault(); save(); }}>

// Event-Typen (TypeScript)
onClick:    React.MouseEvent<HTMLButtonElement>
onChange:   React.ChangeEvent<HTMLInputElement>
onSubmit:   React.FormEvent<HTMLFormElement>
onKeyDown:  React.KeyboardEvent<HTMLInputElement>

Suspense & Error Boundaries

import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary fallback={<p>Something went wrong.</p>}>
  <Suspense fallback={<Spinner />}>
    <AsyncComponent />
  </Suspense>
</ErrorBoundary>

Quick Reference

Hook / API                 Zweck
────────────────────────── ──────────────────────────────
useState                   Lokaler State
useEffect                  Side-Effects, Subscriptions
useRef                     DOM-Refs, mutable Values
useMemo                    Gecachte Berechnung
useCallback                Stabile Funktionsreferenz
useReducer                 Komplexer State mit Actions
useContext / use(Context)  Context lesen
useActionState        ⭐   Form-Action State (pending/result)
useFormStatus         ⭐   Form-Status ohne Prop-Drilling
useOptimistic         ⭐   Optimistic UI Updates
use(Promise)          ⭐   Async Daten in Render lesen
React Compiler        ⭐   Auto-Memoization (Build-Time)

⭐ = Neu in React 19