Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Next.js und Tailwind CSS
    4. React Controllable State Hook: Code und 3 Fallstricke
    Read in English
    1. Blog
    2. Next.js und Tailwind CSS
    3. React Controllable State Hook: Code und 3 Fallstricke
    Next.js und Tailwind CSS
    Next.js und Tailwind CSS

    React Controllable State Hook: Code und 3 Fallstricke

    SR
    Serban Rusu · Gründer von Wingo UI
    16. Okt. 2026 · 11 Min. Lesezeit

    Auf dieser Seite

    0%
    1. Was ist der Unterschied zwischen controlled und uncontrolled Komponenten?
    2. Was macht ein React Controllable State Hook?
    3. Wie schreibe ich eine Komponente, die value, defaultValue und onChange unterstützt?
    4. Was geht schief, wenn eine Komponente zwischen controlled und uncontrolled wechselt?
      1. Ein mit undefined geleerter Wert zeigt veralteten internen State
      2. Beim Laden startet die Komponente uncontrolled
      3. Ein neuer defaultValue wird ignoriert
    5. Wann ruft der Setter onChange auf?
    6. Wie nutzen Switch und Tabs den Hook?
      1. Tabs: Der Hook verwaltet den Wert
      2. Switch: Der Hook speichert, die Komponente meldet
    7. Wie unterscheidet sich der Hook von Radix useControllableState?
    8. Nächste Schritte
    9. Häufige Fragen
      1. Was ist der Unterschied zwischen controlled und uncontrolled Komponenten in React?
      2. Was macht useControllableState?
      3. Darf eine Komponente von uncontrolled zu controlled wechseln?
      4. Warum aktualisiert sich meine Komponente nicht, wenn sich defaultValue ändert?
      5. Wie unterscheidet sich der Hook von Wingo UI von Radix useControllableState?
      6. Ist der Hook useControllableState kostenlos?

    Kurz gesagt

    Ein React Controllable State Hook gibt wie useState ein Paar [value, setValue] zurück, folgt aber dem value-Prop, sobald die Elternkomponente einen übergibt, und hält sonst einen eigenen State, der mit defaultValue startet. Die Komponente ruft bei jeder Interaktion den Setter auf; der Hook speichert den Wert nur im uncontrolled Modus und ruft onChange in beiden Modi auf. Lass jede Instanz ihr ganzes Leben lang in einem Modus: Wer einen Wert mit undefined leert, gibt die Kontrolle stillschweigend an einen veralteten internen State zurück.

    Veröffentlicht am 16. Okt. 2026

    Jedes wiederverwendbare Eingabefeld bekommt irgendwann dieselbe Anfrage. Ein Screen will den Wert selbst verwalten (value plus onChange), ein anderer braucht nur einen Startwert (defaultValue) und will nur erfahren, wenn er sich ändert. Mit einem React Controllable State Hook unterstützt du beides in einer Komponente, ohne zwei Codepfade: Du schreibst die Komponente gegen ein einziges Paar [value, setValue], und der Hook entscheidet, wem der State gehört. Dieses Tutorial baut den Hook, zeigt die Bugs, die entstehen, wenn ein Prop den Modus wechselt, und erklärt, wie Switch und Tabs dasselbe Muster nutzen.

    Was ist der Unterschied zwischen controlled und uncontrolled Komponenten?

    Der Unterschied liegt darin, wem der Wert gehört: der Elternkomponente (controlled) oder der Komponente selbst (uncontrolled). In deutschen Texten heißen sie auch kontrollierte und unkontrollierte Komponenten. Die React-Doku zum Teilen von State (opens in a new tab) beschreibt es so: Eine Komponente ist uncontrolled, wenn ihr wichtiger State in ihr selbst liegt, und controlled, wenn Props der Elternkomponente diesen State bestimmen.

    Das native <input> zeigt beide Formen:

    tsx
    // uncontrolled: das Feld hält den Text, die Elternkomponente legt nur den Startwert fest
    <input defaultValue="Emma Carter" />
    // controlled: die Elternkomponente hält den Text und muss ihn bei jedem Tastendruck aktualisieren
    <input value={name} onChange={(event) => setName(event.target.value)} />

    Das ist der Zielkonflikt bei jeder Entscheidung „React controlled vs uncontrolled“. Uncontrolled bedeutet weniger Code für den Aufrufer. Controlled brauchst du, wenn die Elternkomponente validieren, zurücksetzen, mit der URL synchronisieren oder mehrere Controls von einer Stelle aus steuern muss. Eine Komponente aus einer Bibliothek sollte keine der beiden Varianten erzwingen. Deshalb nimmt sie controlled und uncontrolled Props nebeneinander an: value, defaultValue und onValueChange. Die Namen richten sich nach dem Wert: checked / defaultChecked / onCheckedChange bei einem Switch, open / defaultOpen / onOpenChange bei einem Dialog.

    Was macht ein React Controllable State Hook?

    Er gibt der Komponente einen Wert und einen Setter und versteckt die Frage, wem der State gehört:

    • Solange der value-Prop definiert ist, gibt der Hook ihn zurück und speichert nie eine eigene Kopie. Der Setter ruft nur onChange auf, und die Elternkomponente entscheidet, ob sie die Änderung übernimmt.
    • Solange value undefined ist, hält der Hook den State selbst, beginnend mit defaultValue, und der Setter aktualisiert ihn und ruft onChange auf.

    Hier ist der komplette Hook, wie er in Wingo UI ausgeliefert wird (hooks/use-controllable-state.ts):

    ts
    import { useCallback, useInsertionEffect, useRef, useState, type SetStateAction } from "react";
    export type UseControllableStateParams<T> = {
    value?: T;
    defaultValue: T;
    onChange?: (value: T) => void;
    };
    export function useControllableState<T>({
    value,
    defaultValue,
    onChange,
    }: UseControllableStateParams<T>): [T, (next: SetStateAction<T>) => void] {
    const [uncontrolled, setUncontrolled] = useState(defaultValue);
    const controlled = value !== undefined;
    const current = controlled ? value : uncontrolled;
    // die Werte des letzten Renders, gelesen vom stabilen Setter
    const latest = useRef({ current, controlled, onChange });
    useInsertionEffect(() => {
    latest.current = { current, controlled, onChange };
    });
    const setValue = useCallback((next: SetStateAction<T>) => {
    const { current: prev, controlled: isControlled, onChange: notify } = latest.current;
    const resolved = typeof next === "function" ? (next as (prev: T) => T)(prev) : next;
    if (Object.is(resolved, prev)) return;
    if (!isControlled) {
    latest.current = { ...latest.current, current: resolved };
    setUncontrolled(resolved);
    }
    notify?.(resolved);
    }, []);
    return [current, setValue];
    }

    Auf drei Details kommt es an. Der Setter ist stabil (useCallback ohne Dependencies), also kannst du ihn bedenkenlos in Dependency-Arrays von Effects und in memoisierten Kindkomponenten verwenden. Er liest den aktuellen Wert und den Callback aus einer Ref, sodass eine Elternkomponente, die bei jedem Render ein neues Inline-onChange übergibt, nie einen veralteten bekommt. Und er nimmt wie useState eine Updater-Funktion an, also funktioniert setValue((prev) => !prev) in beiden Modi.

    Die Ref wird in useInsertionEffect geschrieben, nicht während des Renders. latest.current = ... direkt im Render-Body sieht gleichwertig aus. Ein Render, den React verwirft (ein suspendierter oder unterbrochener Concurrent Render), würde die Ref aber auf Werten stehen lassen, die nie committet wurden, und der Lint des React Compilers markiert Ref-Schreibzugriffe während des Renders. Der Insertion Effect läuft vor den Layout Effects. Selbst ein useLayoutEffect in einer Kindkomponente, der den Setter aufruft, sieht also die committeten Werte.

    Installier ihn einzeln mit:

    bash
    npx wingo-ui@latest add use-controllable-state

    Die Doku zu useControllableState listet die Parameter und den Rückgabewert.

    Wie schreibe ich eine Komponente, die value, defaultValue und onChange unterstützt?

    Deklarier die drei Props, gib sie an den Hook weiter und schreib den Rest der Komponente so, als gehöre ihr der State. Ein Toggle-Button:

    tsx
    "use client";
    import { useControllableState } from "@/hooks/use-controllable-state";
    type ToggleProps = {
    pressed?: boolean;
    defaultPressed?: boolean;
    onPressedChange?: (pressed: boolean) => void;
    };
    export function Toggle({ pressed, defaultPressed = false, onPressedChange }: ToggleProps) {
    const [on, setOn] = useControllableState({
    value: pressed,
    defaultValue: defaultPressed,
    onChange: onPressedChange,
    });
    return (
    <button type="button" aria-pressed={on} onClick={() => setOn((prev) => !prev)}>
    {on ? "An" : "Aus"}
    </button>
    );
    }

    Jetzt funktionieren beide Aufrufe mit derselben Komponente:

    tsx
    // uncontrolled: startet eingeschaltet und hält seinen State selbst
    <Toggle defaultPressed onPressedChange={(on) => console.log(on)} />
    // controlled: der State gehört der Elternkomponente, und sie kann eine Änderung ablehnen
    <Toggle pressed={muted} onPressedChange={(next) => setMuted(next)} />

    Die Demo unten zeigt denselben Mengen-Stepper zweimal. Drück auf beiden Karten Plus und Minus: Der linke zählt selbst, der rechte wird von einer Elternkomponente gesteuert, die ihn bei 5 deckelt und zurücksetzen kann.

    Drück auf beiden Steppern Plus: Der uncontrolled zählt bis 9, der controlled bleibt bei 5 stehen, weil seine Elternkomponente höhere Werte ablehnt
    $ npx wingo-ui@latest add use-controllable-state
    FreeDoku: useControllableState

    Beachte, was die Obergrenze auf der controlled Seite kostet: nichts im Stepper. Die Elternkomponente bekommt onChange(6), speichert 5, und der Stepper rendert den value, den er bekommt.

    Was geht schief, wenn eine Komponente zwischen controlled und uncontrolled wechselt?

    Die Komponente wechselt den Besitzer, ohne es jemandem zu sagen, und zeigt einen Wert, mit dem niemand rechnet. Der Hook entscheidet bei jedem Render mit value !== undefined über den Modus, also kann der Aufrufer ihn versehentlich umschalten. Die React-Referenz zu input (opens in a new tab) nennt die Regel für native Inputs: Ein Input soll während seiner gesamten Lebensdauer nicht zwischen controlled und uncontrolled wechseln, und React loggt eine Warnung, wenn es das doch tut. Zwei der folgenden Fallstricke kommen von diesem Wechsel, der dritte davon, dass defaultValue wie ein Wert behandelt wird.

    Ein mit undefined geleerter Wert zeigt veralteten internen State

    Der klassische Fall ist eine Tab-Leiste, die an optionale Daten gebunden ist:

    tsx
    // falsch: hat der Nutzer keinen Tarif, werden die Tabs uncontrolled
    <Tabs options={plans} value={user.plan} onValueChange={setPlan} />

    Solange user.plan ein String ist, gehört der Tab der Elternkomponente, und der Hook schreibt nie in seinen internen State. Dieser State enthält aber noch, was er hatte, bevor die Elternkomponente übernommen hat, oft den ursprünglichen defaultValue (bei Tabs die erste aktivierte Option). Sobald user.plan zu undefined wird, gibt der Hook diesen alten Wert zurück, und kein onChange informiert die Elternkomponente.

    Die Lösung: Halt den Wert definiert. Ersetz ihn durch einen Fallback (value={user.plan ?? ""}, das Tabs ohne aktiven Tab rendert), oder nimm in deinen eigenen Komponenten null für „nichts ausgewählt“. Der Hook von Wingo UI behandelt nur undefined als uncontrolled, also bleibt null ein controlled leerer Wert. Radix macht denselben Check mit prop !== undefined. Native Inputs sind strenger: React will als value einen String, nie null, also nimm dort "" als Fallback.

    Beim Laden startet die Komponente uncontrolled

    Das Gegenstück tritt beim ersten Laden auf:

    tsx
    // falsch: uncontrolled, bis der Request fertig ist, dann übernimmt der Serverwert
    <Tabs options={plans} value={settings.data?.plan} onValueChange={savePlan} />

    Während der Request läuft, ist value undefined. Die Tabs halten den State also selbst, und der Nutzer kann schon herumklicken. Kommen die Daten an, wird die Komponente controlled und springt auf den Serverwert; der Tab, den der Nutzer gewählt hat, ist weg. Hat savePlan diese Auswahl schon gespeichert, zeigt der Screen jetzt womöglich einen veralteten Wert aus der ersten Antwort. Render das Control erst, wenn die Daten da sind, oder lass es uncontrolled und mounte es mit key={settings.data.plan} und defaultValue={settings.data.plan}, sobald die Daten vorliegen.

    Ein neuer defaultValue wird ignoriert

    defaultValue ist der Startwert von useState und wird deshalb einmal gelesen, beim Mount. Eine spätere Änderung bewirkt nichts. Das ist richtig (es ist ein Default, kein Wert) und beim ersten Mal trotzdem überraschend. Soll ein neuer Default die Komponente neu starten, ändere ihren key. Die Stepper-Demo oben macht genau das: Das defaultValue-Control im Playground ist zugleich der key des Steppers. Mit demselben Trick gibt eine Elternkomponente die Kontrolle sauber ab: Sie mountet die Komponente mit einem neuen key neu und übergibt den aktuellen Wert als defaultValue.

    Wann ruft der Setter onChange auf?

    Nur wenn sich der Wert wirklich ändert. Der Setter berechnet den nächsten Wert, vergleicht ihn per Object.is mit dem aktuellen und bricht ab, wenn beide gleich sind. Ein Klick auf einen schon aktiven Tab löst also kein onValueChange aus, und eine Elternkomponente, die Änderungen loggt, sieht nur echte Änderungen. Objekte werden per Referenz verglichen: Ein neues Objekt mit gleichem Inhalt zählt trotzdem als Änderung.

    Object.is statt !== ist bei Zahlen wichtig. NaN !== NaN ist true. Mit einem !==-Check würde ein Zahlenfeld, das seinen leeren Text zu NaN parst, also jedes Mal onChange(NaN) auslösen, wenn es diesen leeren Text erneut parst. Object.is(NaN, NaN) ist true, also meldet der Hook nichts. Es ist derselbe Vergleich, mit dem useState einen Re-Render überspringt.

    Der Aufruf ist synchron, im Setter, in beiden Modi. In einem Event-Handler heißt das: Das setState der Elternkomponente in onChange wird mit dem Update der Komponente gebatcht, und beide rendern zusammen.

    Eine Feinheit solltest du kennen. Im uncontrolled Modus bauen zwei Updater im selben Event aufeinander auf, wie bei useState: Zweimal setValue((n) => n + 1) addiert 2. Im controlled Modus ändert sich der Wert erst, wenn die Elternkomponente neu rendert. Beide Updater sehen also dasselbe prev und melden zweimal dieselbe Zahl. Radix verhält sich genauso, weil auch sein controlled Setter den Updater gegen den aktuellen Prop auflöst. Muss eine Komponente mehrere Schritte auf einmal anwenden, berechne den Endwert und ruf den Setter einmal auf.

    Wie nutzen Switch und Tabs den Hook?

    152 der 227 Dateien in components/ui importieren useControllableState (im Oktober 2026 im Repository gezählt). Die Konvention ist ein Wert-Prop, ein Default-Prop und ein Change-Callback, benannt nach dem Wert. Tabs und Switch zeigen die zwei Wege, das zu verdrahten.

    Tabs: Der Hook verwaltet den Wert

    Die einfache Tabs-API reicht value, defaultValue und onValueChange direkt an den Hook weiter, mit einer Besonderheit der Bibliothek: Fehlt defaultValue, startet Tabs auf der ersten aktivierten Option. Uncontrolled ist das eine Zeile:

    tsx
    import { Tabs, type TabsOption } from "@/components/ui/tabs";
    const options: TabsOption[] = [
    { value: "active", label: "Aktiv", badge: 12, content: <p>12 Inserate sind in New York online.</p> },
    { value: "pending", label: "Ausstehend", badge: 3, content: <p>3 Inserate warten auf Prüfung.</p> },
    { value: "sold", label: "Verkauft", content: <p>Letzter Verkauf: 2. Sep. 2026.</p> },
    ];
    export function MyListings() {
    return <Tabs options={options} defaultValue="pending" aria-label="Meine Inserate" />;
    }

    Im controlled Modus hält die Elternkomponente den Tab, zum Beispiel um ihn mit etwas anderem auf der Seite synchron zu halten (dieselben options wie oben):

    tsx
    "use client";
    import { useState } from "react";
    import { Tabs } from "@/components/ui/tabs";
    export function ListingsPanel() {
    const [tab, setTab] = useState("active");
    return <Tabs options={options} value={tab} onValueChange={setTab} aria-label="Meine Inserate" />;
    }

    Weil der Setter über den Hook läuft, kann Tabs den Wert auch selbst ändern und eine controlled Elternkomponente trotzdem informieren: Verschwindet der aktive Tab aus options, ruft Tabs den Setter mit dem ersten aktivierten Tab auf, und eine controlled Elternkomponente bekommt das über onValueChange mit.

    Switch: Der Hook speichert, die Komponente meldet

    Switch nutzt den Hook ohne onChange:

    ts
    const [checked, setChecked] = useControllableState({ value: checkedProp, defaultValue: defaultChecked });

    Der Grund ist der Rückgabewert. onCheckedChange ist als (checked: boolean) => void | Promise<unknown> typisiert, und der Switch braucht dieses Promise: Er schaltet sofort um, zeigt während des Speicherns einen Spinner im Thumb und schaltet zurück, wackelt und zeigt den Fehlertext, wenn das Promise rejected wird. Der Hook ruft onChange auf und verwirft, was zurückkommt. Deshalb ruft der Switch onCheckedChange selbst auf und nutzt den Hook nur zum Speichern. Das ist eine brauchbare Regel für deine eigenen Komponenten: Wenn das Ergebnis des Callbacks zählt, ruf ihn direkt auf und lass den Hook den Wert halten.

    tsx
    "use client";
    import { Switch } from "@/components/ui/switch";
    async function saveSetting(key: string, on: boolean) {
    const res = await fetch("/api/settings", {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ [key]: on }),
    });
    if (!res.ok) throw new Error("Speichern fehlgeschlagen");
    }
    export function OffersSetting() {
    return (
    <Switch
    label="Preisangebote"
    defaultChecked
    errorText="Speichern fehlgeschlagen. Versuch es noch mal."
    onCheckedChange={(on) => saveSetting("offers", on)}
    />
    );
    }

    In der Demo unten schaltet der Button „Simulate an error“ den ersten Switch mit einem Speichervorgang um, der fehlschlägt. Schaltest du selbst einen Switch um, bleibt die Änderung bestehen.

    Drück auf Simulate an error: Der erste Switch schaltet sofort um, zeigt einen Spinner im Thumb, springt dann zurück und zeigt den Fehler
    $ npx wingo-ui@latest add switch
    FreeDoku: Switch

    In diesem uncontrolled Aufbau hält der Switch den Wert, und die Elternkomponente speichert ihn nie; das Promise entscheidet nur, ob das Umschalten bleibt. Braucht ein Formular den Wert im State der Elternkomponente, übergib stattdessen checked und onCheckedChange und setz checked, wenn das Speichern geklappt hat.

    Wie unterscheidet sich der Hook von Radix useControllableState?

    Radix useControllableState hat dieselbe Grundform, unterscheidet sich aber im Detail. Radix Primitives nutzen den Hook intern, und er ist auf npm als @radix-ui/react-use-controllable-state veröffentlicht (Version 1.3.0, Stand Oktober 2026). Jede shadcn/ui-Komponente, die auf Radix aufbaut, erbt also sein Verhalten. Verglichen mit dem Radix-Quellcode auf GitHub (opens in a new tab), Stand Oktober 2026:

    Wingo UI useControllableStateRadix useControllableState
    Optionenvalue, defaultValue, onChangeprop, defaultProp, onChange, caller
    Controlled, wennvalue !== undefinedprop !== undefined
    Änderungs-CheckObject.is!==
    Uncontrolled onChangeim Setter aufgerufenaus einem Effect nach dem Render aufgerufen
    Identität des Settersstabil für das ganze Leben der Komponenteneu, sobald sich der Prop oder der Modus ändert
    Warnung beim Moduswechselkeineein console.warn im Development, mit caller im Text
    Installationals Quellcode in dein Projekt kopiertein npm-Paket

    Zwei Zeilen ändern, wie du Code drumherum schreibst. Der Setter von Radix führt prop in seinen useCallback-Dependencies. Im controlled Modus ist er also bei jeder Wertänderung eine neue Funktion, und ein Effect, der von ihm abhängt, läuft bei jeder Änderung erneut. Und weil Radix uncontrolled Änderungen aus einem Effect meldet, rendert eine Elternkomponente, die den Wert in onChange speichert, einen Commit später als die Komponente.

    Die Warnung ist der einzige Punkt, den wir als Grund nennen würden, Radix vorzuziehen: Sie fängt die oben beschriebenen Moduswechsel schon im Development ab. Unser Hook bleibt eine einzige Datei, die dir gehört, mit Namen, die zu den Props passen, die er bedient.

    Nächste Schritte

    Kopier den Hook mit npx wingo-ui@latest add use-controllable-state und nutz ihn in deiner nächsten Komponente, die einen Wert-Prop braucht. Switch und Tabs sind ebenfalls kostenlos: Die Doku zur Tabs-Komponente listet die Props value, defaultValue und onValueChange, und die Doku zur Switch-Komponente erklärt das asynchrone Speichern mit onCheckedChange. Wenn du deine Komponenten gleichzeitig auf React 19 umstellst, behandelt ref als Prop in React 19 die andere Hälfte einer modernen Komponenten-API, und der Guide zu Design Tokens in Tailwind v4 ist der Einstieg in die übrigen Artikel zu Next.js und Tailwind CSS.

    Komponenten in diesem Artikel

    • useControllableState

      A React hook for controlled and uncontrolled state: it follows a value prop when you pass one and keeps its own state when you do not.

      Free
    • Switch

      A React toggle switch for settings that apply at once: a spring thumb that stretches and drags, thumb icons, and async saves that roll back.

      Free
    • Tabs

      React tabs with a sliding indicator that switch views of one page: underline for sections, pill for filters, segmented for a compact switch.

      Free

    Häufige Fragen

    Was ist der Unterschied zwischen controlled und uncontrolled Komponenten in React?

    Eine controlled Komponente zeigt den Wert, den die Elternkomponente übergibt, und meldet Änderungen über einen Callback; der State gehört also der Elternkomponente. Eine uncontrolled Komponente hält ihren State selbst, meist mit einem defaultValue-Prop als Startwert, und die Elternkomponente erfährt nur von Änderungen.

    Was macht useControllableState?

    Der Hook gibt wie useState einen Wert und einen Setter zurück. Solange der value-Prop definiert ist, gibt er diesen Prop zurück und der Setter ruft nur onChange auf; ist er undefined, speichert der Hook den Wert selbst, beginnend mit defaultValue.

    Darf eine Komponente von uncontrolled zu controlled wechseln?

    Sie sollte es nicht. React warnt, wenn ein Input das tut, Radix warnt im Development, und der Hook von Wingo UI folgt einfach dem, was er bekommt, und zeigt dann einen veralteten Wert, wenn die Kontrolle zurückgeht. Leg dich pro Instanz auf einen Modus fest und nimm null statt undefined für einen leeren controlled Wert.

    Warum aktualisiert sich meine Komponente nicht, wenn sich defaultValue ändert?

    defaultValue wird einmal gelesen, beim Mount, genau wie der Startwert von useState. Um mit einem neuen Default neu zu starten, gib der Komponente einen neuen key oder steuere sie über value.

    Wie unterscheidet sich der Hook von Wingo UI von Radix useControllableState?

    Radix nennt die Optionen prop, defaultProp, onChange und caller, vergleicht mit !== und ruft onChange bei uncontrolled Änderungen in einem Effect nach dem Render auf. Der Hook von Wingo UI nimmt value, defaultValue und onChange, vergleicht mit Object.is und ruft onChange synchron im Setter auf, ohne Warnung im Development.

    Ist der Hook useControllableState kostenlos?

    Ja. Der Hook ist kostenlos, ebenso Switch und Tabs, die auf ihm aufbauen. Installier ihn mit npx wingo-ui@latest add use-controllable-state.

    • React
    • Hooks
    • State
    • TypeScript
    • Komponenten-API

    Teilen

    SR

    Über den Autor

    Serban Rusu

    Gründer von Wingo UI

    Serban Rusu hat Wingo UI gegründet. Er baut die Komponenten, die CLI und den MCP-Server und schreibt über React-UIs für Smartphones und KI-Agents.

    Mehr von Serban
    Weiterlesen

    Ähnliche Artikel

    Alle Artikel
    Praxis: Screens und Apps

    React Settings Page: Navigation, Save Bar und Danger Zone

    Bau eine React Settings Page mit Seitennavigation am Desktop, iOS-Liste auf dem Smartphone, Save Bar für offene Änderungen und abgesicherter Danger Zone.

    SRSerban Rusu·16. Okt. 2026·11 Min. Lesezeit
    Mobile UI mit React

    React Swipeable Tabs: Seiten, die dem Daumen folgen

    So baust du React Swipeable Tabs mit nativem Scroll Snap: Der Indikator folgt dem Finger, vertikales Scrollen wechselt nie den Tab, mit Tastatur, ohne Altlast.

    SRSerban Rusu·16. Okt. 2026·11 Min. Lesezeit
    Komponenten-Guides

    Framer Motion Spring: Presets für Stiffness und Damping

    Vier Framer Motion Spring Presets mit echten Werten für Stiffness und Damping: wofür sich jedes eignet und wie du sie in deiner React-Bibliothek teilst.

    SRSerban Rusu·13. Okt. 2026·9 Min. Lesezeit
    Newsletter

    Neue Artikel per E-Mail

    Neue Guides, Tutorials und Vergleiche aus dem Wingo UI Blog, sobald sie erscheinen. Die meisten Artikel sind auf Englisch.

    Kein Spam. Du kannst dich jederzeit abmelden.

    WingoUI

    Animierte, konfigurierbare, mobile-first React-Komponenten und Blöcke. Kopier den Quellcode, pass ihn an und lass deinen Coding-Agenten damit bauen.

    Produkt

    • Komponenten
    • Vorlagen
    • Preise
    • KI-Agenten
    • Theme-Generator

    Ressourcen

    • Doku
    • Blog
    • Changelog
    • Changelog-RSS
    • llms.txt

    Rechtliches

    • AGB
    • Datenschutz
    • Rückerstattung
    • Lizenz
    • Impressum

    Komponenten-Kategorien

    • Buttons & Actions
    • Inputs
    • Forms
    • Navigation
    • Overlays
    • Feedback
    • Data Display
    • Tables & Lists
    • Charts & Stats
    • Layout
    • Media
    • AI Kit
    • Text & Effects
    • Mobile
    • Commerce
    • Marketing Sections
    • Blocks
    • Hooks & Utilities

    © 2026 Wingo UI

    Wingo UI