# React Phone Input mit Ländervorwahl und E.164-Wert

> React Phone Input, der beim Tippen pro Land formatiert, das Land aus einer eingefügten +Vorwahl erkennt, mit libphonenumber-js prüft und sauberes E.164 liefert.

- Autor: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Veröffentlicht: 13. Okt. 2026
- Kategorie: [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components)
- Lesezeit: 8 Min.
- Kanonische URL: https://wingo-ui.com/de/blog/react-phone-input
- Englische Fassung: https://wingo-ui.com/blog/react-phone-input

## Kurz gesagt

Ein React Phone Input sollte Nutzer die Nummer so tippen lassen, wie ihr Land sie schreibt, das Land aus einer durchsuchbaren Liste oder einer eingefügten +Vorwahl übernehmen und deinem Code einen einzigen E.164-String wie +12015550123 liefern statt formatiertem Text. Validiere im Client für das Feedback und noch einmal auf dem Server mit libphonenumber-js, mit den max-Metadaten, wenn du die Ziffern streng prüfen willst. Der Phone Input von Wingo UI übernimmt Formatierung, Ländererkennung, E.164-Wert und eine Länderliste als Bottom Sheet auf Smartphones, gebaut auf libphonenumber-js.

Ein React Phone Input sieht aus wie ein einzelnes Textfeld, dahinter stecken aber vier Probleme: ein Land aus mehr als 200 auswählen, die Ziffern so formatieren, wie dieses Land sie schreibt, Nummern abfangen, die es nicht geben kann, und einen sauberen Wert in deine Datenbank bekommen. Die meisten Formulare lösen eins davon und überlassen den Rest einem Regex. So landen für denselben Kunden `(201) 555-0123`, `2015550123` und `+1 201 555 0123` in der Datenbank. Dieser Guide zeigt, was ein gutes Telefonfeld können muss, wie die Validierung mit libphonenumber-js wirklich funktioniert und wie du den [Phone Input](https://wingo-ui.com/components/phone-input) von Wingo UI in einem echten Formular nutzt.

## Was muss ein React Phone Input können?

Sechs Eigenschaften unterscheiden ein Telefonfeld, das niemandem auffällt, von einem, mit dem man kämpft:

1. **Beim Tippen formatieren, passend zum gewählten Land.** Eine US-Nummer erscheint beim Tippen als `201 555 0123`, eine britische Mobilnummer als `7400 123456`, und der Cursor bleibt hinter der Ziffer, die du gerade getippt hast, statt ans Ende zu springen.
2. **Das Land aus einer eingefügten oder automatisch ausgefüllten Nummer erkennen.** Wer `+44 7400 123456` oder `0044 7400…` tippt oder einfügt, sollte die Flagge von selbst auf das Vereinigte Königreich wechseln sehen.
3. **Das Trunk-Präfix entfernen.** Leute tippen die Nummer so, wie sie sie zu Hause wählen, oft mit einer führenden `0` (oder einer `1` in den USA). Das Feld sollte nur die nationale Nummer behalten.
4. **Eine durchsuchbare Länderliste.** Nach lokalisiertem Namen, englischem Namen, ISO-Code und Vorwahl, mit den Ländern, die deine Nutzer am häufigsten wählen, ganz oben.
5. **Ein einziger Wert als Ergebnis.** Dein Formular bekommt `+12015550123`, nie den formatierten Text.
6. **Die richtige Tastatur auf Smartphones.** `inputMode="tel"` und ein Autocomplete-Hinweis, damit der Browser die gespeicherte Nummer anbietet.

## Welche React Phone Input Bibliotheken gibt es?

Stand Oktober 2026, laut npm-Registry und der README des jeweiligen Projekts:

| Option | Letztes Release | Basis | Styling |
|---|---|---|---|
| [react-phone-input-2](https://github.com/bl00mber/react-phone-input-2) | 2.15.1, Jul 2022 | eigene Länderdaten | `style.css` |
| [react-phone-number-input](https://www.npmjs.com/package/react-phone-number-input) | 3.4.18, Aug 2026 | libphonenumber-js | `style.css` |
| [react-international-phone](https://www.npmjs.com/package/react-international-phone) | 4.8.0, Feb 2026 | eigene Länderdaten | `style.css` |
| [shadcn-phone-input](https://github.com/omeralpi/shadcn-phone-input) | kopierter Quellcode | react-phone-number-input | Tailwind |
| Wingo UI Phone Input | kopierter Quellcode | libphonenumber-js | Tailwind v4 |

Alle Optionen stehen unter MIT-Lizenz, bis auf die Komponente von Wingo UI, die zum kostenpflichtigen Pro-Plan gehört. Jedes npm-Paket verlangt, dass du sein eigenes Stylesheet importierst, und shadcn-phone-input braucht laut README zusätzlich cmdk 1.0.0. Wenn du ein kostenloses npm-Paket willst: react-phone-number-input stammt vom Autor von libphonenumber-js und hatte im August 2026 ein Release. Suchst du wegen des Alters eine react-phone-input-2 Alternative, passt jede der neueren Zeilen. Einen shadcn Phone Input gibt es nicht in der offiziellen shadcn/ui-Registry (63 Einträge, Stand Oktober 2026), deshalb greifen shadcn-Projekte zu einem Community-Wrapper wie shadcn-phone-input.

## Wie baust du einen React Phone Input mit Ländervorwahl ein?

Installier ihn mit `npx wingo-ui@latest add phone-input` und render ihn dann mit einem Standardland und ein paar bevorzugten Ländern, die oben in der Liste stehen:

```tsx
"use client";

import { useState } from "react";
import { PhoneInput, type PhoneDetails } from "@/components/ui/phone-input";

export function ContactPhone() {
  const [phone, setPhone] = useState("");
  const [details, setDetails] = useState<PhoneDetails | null>(null);

  return (
    <div className="flex flex-col gap-2">
      <PhoneInput
        name="phone"
        label="Telefon"
        description="Wir rufen nur wegen deiner Bestellung an."
        defaultCountry="US"
        preferredCountries={["US", "CA", "GB"]}
        locale="en-US"
        value={phone}
        onValueChange={(e164, info) => {
          setPhone(e164);
          setDetails(info);
        }}
        showValidity
      />
      {details?.valid && (
        <p className="text-sm text-muted-foreground">Wir rufen {details.international} an.</p>
      )}
    </div>
  );
}
```

Probier es unten aus: Tipp eine Nummer, füg dann eine ein, die mit `+44` beginnt, und sieh zu, wie die Flagge wechselt.

> Live-Demo (Phone Input): Tipp 2015550123 und sieh zu, wie die Nummer als US-Nummer formatiert wird, füg dann +44 7400 123456 ein: Das Land wechselt zum Vereinigten Königreich, und der grüne Haken erscheint, sobald die Nummer gültig ist. Probier sie unter [Phone Input](https://wingo-ui.com/components/phone-input) aus und installier sie mit `npx wingo-ui@latest add phone-input`.

Die wichtigsten Props:

- **`defaultCountry`** setzt das Startland per ISO-Code. Ab Werk steht er auf `"RO"`, stell ihn also auf deinen Markt ein.
- **`preferredCountries`** zeigt diese Länder zuerst unter einer Überschrift „Suggested“. Der Standard ist `["RO", "MD"]`; übergib ein leeres Array, um die Überschriften wegzulassen.
- **`countries`** schränkt die Liste ein und damit auch die Länder, die eine getippte Vorwahl auswählen darf. Standardmäßig sind alle 245 verfügbar, in einer virtualisierten Liste.
- **`countrySelect={false}`** legt das Land fest: kein Picker, die Vorwahl erscheint als Text-Präfix, und ein eingefügtes `+44…` füllt trotzdem die nationalen Ziffern aus.
- **`locale`** bestimmt die Sprache der Ländernamen über `Intl.DisplayNames`. Die englischen Namen bleiben in jeder Sprache durchsuchbar.

## Welchen Wert gibt der Phone Input zurück?

`onValueChange(e164, details)` feuert bei jeder Änderung. `e164` ist die Nummer im E.164-Format, etwa `+12015550123`, sobald die Nummer für das Land möglich ist, und davor ein leerer String. `details` ist `{ country, national, international, valid, possible }`. So unterscheidest du ein leeres Feld von einem unvollständigen und zeigst die formatierten Varianten an, ohne selbst zu formatieren.

Mit `name` rendert die Komponente zusätzlich ein verstecktes Input-Feld mit dem E.164-Wert. Ein einfaches Formular oder eine Server Action bekommt also die saubere Nummer:

```tsx
import { PhoneInput } from "@/components/ui/phone-input";
import { Button } from "@/components/ui/button";
import { isValidPhoneNumber } from "libphonenumber-js/max";

async function requestCallback(formData: FormData) {
  "use server";
  const phone = String(formData.get("phone") ?? "");
  // max-Metadaten: prüft die Ziffern, nicht nur die Länge
  if (!isValidPhoneNumber(phone)) return;
  console.log("call back", phone);
}

export function CallbackForm() {
  return (
    <form action={requestCallback} className="flex flex-col gap-4">
      <PhoneInput name="phone" label="Telefon" defaultCountry="US" preferredCountries={["US", "CA"]} required />
      <Button type="submit">Rückruf anfordern</Button>
    </form>
  );
}
```

Das sichtbare Feld enthält formatierte nationale Ziffern. Deshalb liest du es nie direkt aus. Lies das versteckte Feld oder das Argument `e164`.

## Wie kannst du im React Phone Input die Telefonnummer validieren?

Über libphonenumber-js, und die Bibliothek beantwortet zwei verschiedene Fragen:

- **`isPossible()`**: Passt die Länge für dieses Land?
- **`isValid()`**: Passen die Ziffern zu einem echten Nummernbereich dieses Landes?

Die [README von libphonenumber-js](https://github.com/catamphetamine/libphonenumber-js) nennt einen Haken: Die Standard-Metadaten `min`, rund 80 kB, enthalten nicht die genauen Muster für die Ziffernprüfung. Mit ihnen verhält sich `isValid()` also wie `isPossible()`. Die `max`-Metadaten bringen rund 65 kB dazu und prüfen die Ziffern. Der Phone Input liefert `min` aus, damit er im Browser klein bleibt, und das reicht für Feedback beim Tippen völlig. Auf dem Server, wo die Größe keine Rolle spielt, importierst du aus `libphonenumber-js/max`, wie in der Server Action oben.

Für Formulare mit react-hook-form liefert die kostenlose [Field](https://wingo-ui.com/components/field)-Anatomie Label, Beschreibung und Fehler, und die [Helfer zur Formularvalidierung](https://wingo-ui.com/components/form-validation), ebenfalls ein Pro-Eintrag, geben dir eine zod-Regel mit fertig formulierter Fehlermeldung. Weil das sichtbare Feld formatierten Text enthält, bindest du den Phone Input über einen `Controller` an:

```tsx
"use client";

import { useState } from "react";
import { z } from "zod";
import { Controller } from "react-hook-form";
import { Button } from "@/components/ui/button";
import { PhoneInput } from "@/components/ui/phone-input";
import { createValidators, fieldError, useZodForm } from "@/lib/form-validation";

const v = createValidators();
const schema = z.object({ phone: v.phone({ country: "US" }) });

export function PhoneForm({ onSave }: { onSave: (values: z.output<typeof schema>) => Promise<void> }) {
  const form = useZodForm(schema, { defaultValues: { phone: "" } });
  // die getippten Ziffern, damit eine unvollständige Nummer die Telefon-Meldung bekommt statt "required"
  const [national, setNational] = useState("");
  const error = fieldError(form, "phone");

  return (
    <form onSubmit={form.handleSubmit(onSave)} noValidate className="flex flex-col gap-4">
      <Controller
        control={form.control}
        name="phone"
        render={({ field }) => (
          <PhoneInput
            label="Telefon"
            defaultCountry="US"
            value={field.value}
            onValueChange={(e164, details) => {
              setNational(details.national);
              field.onChange(e164);
            }}
            onBlur={field.onBlur}
            ref={field.ref}
            error={error && national ? "Gib eine gültige Telefonnummer ein" : error}
            required
          />
        )}
      />
      <Button type="submit" loading={form.formState.isSubmitting}>
        Speichern
      </Button>
    </form>
  );
}
```

`v.phone()` prüft den Wert mit `isValidPhoneNumber` aus den Standard-Metadaten `min`. Im Browser ist das also eine Längenprüfung. `useZodForm` zeigt Fehler, nachdem das Feld verlassen wurde, und aktualisiert sie danach beim Tippen. Der State `national` entschärft eine Falle: Solange die Nummer zu kurz ist, um möglich zu sein, schickt `onValueChange` einen leeren String. Dann meldet zod „This field is required“ für ein Feld, das die Person offensichtlich ausgefüllt hat. Mit `details.national` zeigst du stattdessen „Gib eine gültige Telefonnummer ein“, sobald etwas getippt wurde.

## Wie verhält sich der Phone Input auf dem Smartphone und mit der Tastatur?

Unter 768px öffnet sich die Länderliste als Bottom Sheet mit Suchfeld und 48px hohen Zeilen statt als Popover. Eine Liste mit 245 Zeilen, verankert an einem kleinen Flaggen-Button, lässt sich mit dem Daumen schlecht scrollen. `responsive={false}` behält das Popover; unser [Guide zum React Bottom Sheet](https://wingo-ui.com/de/blog/react-bottom-sheet-for-the-web) erklärt, wie diese Sheets gezogen werden und einrasten. Das Nummernfeld nutzt `inputMode="tel"` für die Telefontastatur, standardmäßig `autoComplete="tel-national"` und `enterKeyHint="next"`; setz es im letzten Feld eines Formulars auf `"done"`. Auf Smartphones ist der Text 16px groß, damit iOS Safari nie ins Feld zoomt, und der Flaggen-Button behält eine Trefferfläche von 44px.

Mit der Tastatur erreichst du per Tab zuerst den Flaggen-Button und dann das Nummernfeld. Auf dem Flaggen-Button öffnen Enter, Leertaste oder Pfeil nach unten die Liste, und ein Buchstabe springt zum nächsten Land mit diesem Anfangsbuchstaben, ohne die Liste zu öffnen. In der Liste hat die Suche den Fokus. Pfeiltasten, Home, End, PageUp und PageDown bewegen die Auswahl, Enter wählt aus und setzt den Fokus zurück ins Nummernfeld, und Escape schließt die Liste und kehrt zum Flaggen-Button zurück. Der Accessible Name des Flaggen-Buttons enthält Land und Vorwahl, etwa „Country: United States +1“.

Dient die Nummer dazu, einen Login- oder Bestätigungscode zu empfangen, folgt auf dem nächsten Screen ein Code-Feld; unser [Guide zum React OTP Input](https://wingo-ui.com/de/blog/react-otp-input) behandelt Einfügen und SMS-Autofill dafür.

## Welche Fallstricke hat ein Phone Input in Produktion?

- **Formatierten Text speichern.** `(201) 555-0123` verliert das Land, und Lookups funktionieren nicht mehr. Speichere E.164 und formatiere für die Anzeige mit `details.national` oder `details.international`.
- **Dem Client vertrauen.** Ein Request kann dein Formular umgehen. Prüf den E.164-Wert auf dem Server noch einmal.
- **Flaggen unter Windows.** Windows rendert keine Flaggen-Emojis, deshalb zeigt der Phone Input dort nach dem Mount den ISO-Code in einem kleinen Chip. Übergib `renderFlag`, um überall deine eigenen SVG-Flaggen zu nutzen.
- **Masken, die gegen das Einfügen arbeiten.** Eine feste Maske wie `(999) 999-9999` lehnt ein eingefügtes `+1 201…` ab. Formatiere stattdessen pro Land aus den Ziffern und erkenne die Vorwahl. Für Formate, die wirklich fest sind, etwa eine Postleitzahl, ist ein maskiertes Eingabefeld das bessere Werkzeug.

Weitere Deep Dives zu einzelnen Komponenten findest du in den [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components), und unser Guide zu [React-Formularkomponenten](https://wingo-ui.com/de/blog/react-form-components-guide) zeigt, wie das Telefonfeld mit E-Mail-, Adress- und Zahlungsfeldern zusammenpasst.

## Wie installierst du ihn?

Führ `npx wingo-ui@latest add phone-input` aus. Der Befehl kopiert den Phone Input mit den Select- und Field-Teilen, die er nutzt, und installiert `libphonenumber-js`, `motion` und `lucide-react`. Der Phone Input gehört zu [Wingo UI Pro](https://wingo-ui.com/de/pricing), also meld dich vorher mit `npx wingo-ui@latest login` an; die Field-Anatomie, die er rendert, ist für sich allein kostenlos.

## Komponenten in diesem Artikel

- [Phone Input](https://wingo-ui.com/components/phone-input) (Pro): A React phone number input with a searchable country picker, formatting as you type, validation and one clean E.164 value out. Installation: `npx wingo-ui@latest add phone-input`
- [Field](https://wingo-ui.com/components/field) (Free): A React form field wrapper every control shares: label, hint, animated error and counter, fieldsets, and the box recipe all inputs use. Installation: `npx wingo-ui@latest add field`
- [Form validation](https://wingo-ui.com/components/form-validation) (Pro): Zod validation rules for React forms with one message set (English or Romanian), react-hook-form glue and a pretend request. Installation: `npx wingo-ui@latest add form-validation`

## Häufige Fragen

### Wie baue ich in React einen Phone Input mit Ländervorwahl?

Setz einen Länder-Button mit Flagge und Vorwahl vor das Nummernfeld, formatiere die nationalen Ziffern beim Tippen für dieses Land und wechsle das Land, wenn jemand eine Nummer mit + oder 00 am Anfang tippt oder einfügt. Speichere das Ergebnis als einen E.164-String wie +12015550123.

### Was ist eine gute Alternative zu react-phone-input-2?

Das letzte npm-Release von react-phone-input-2, 2.15.1, stammt vom Juli 2022. Optionen mit aktuellen Releases sind react-phone-number-input und react-international-phone auf npm, Wrapper im shadcn-Stil auf Basis von react-phone-number-input und der Phone Input von Wingo UI, den du als Quellcode in dein Projekt kopierst und mit Tailwind CSS stylst.

### Wie validiere ich eine Telefonnummer in React?

Nutze libphonenumber-js: isPossible() prüft die Länge für das Land, isValid() prüft die Ziffern. Die Standard-Metadaten min prüfen nur die Länge, also importierst du auf dem Server aus libphonenumber-js/max, wenn du die Ziffern streng validieren willst, und prüfst den E.164-Wert dort immer noch einmal.

### Sollte ich Telefonnummern im E.164-Format speichern?

Ja. E.164 ist das internationale Format mit Pluszeichen, Ländervorwahl und nationaler Nummer ohne Leerzeichen, etwa +442071838750. Es ist eindeutig, lässt sich als einfacher Text sortieren und vergleichen und ist das, was SMS- und Telefonie-APIs erwarten.

### Hat shadcn/ui einen Phone Input?

Nicht in der offiziellen Registry, Stand Oktober 2026. Community-Komponenten wie shadcn-phone-input verpacken react-phone-number-input im shadcn-Styling.

---

Quelle: https://wingo-ui.com/de/blog/react-phone-input
