iToverDose/Software· 12 JUNI 2026 · 16:02

Modale in React mit Typen und Promises sicher nutzen

Erfahren Sie, wie Sie modale Dialoge in React mit typsicheren Promises statt booleschen Zuständen verwalten. Das eliminiert Callback-Ketten und verhindert typische Fehlerquellen in Anwendungen.

DEV Community4 min0 Kommentare

Modale Dialoge in React-Anwendungen werden oft als einfache UI-Elemente behandelt – gesteuert durch boolesche Flags, bedingte Rendering-Logik oder Callback-Funktionen. Diese Herangehensweise mag für einfache Bestätigungsdialoge ausreichen, doch komplexe Geschäftsprozesse erfordern eine präzisere Steuerung.

Stellen Sie sich vor, ein Nutzer soll einen Bericht umbenennen, ein Datum auswählen oder eine Konfliktsituation lösen, bevor die Anwendung fortfährt. Solche Abläufe benötigen nicht nur einen Dialog, sondern eine typisierte Eingabe, eine strukturierte Ausgabe und die Möglichkeit, das Ergebnis asynchron zu verarbeiten – ähnlich wie bei anderen asynchronen Operationen in Ihrer Anwendung.

const result = await modal.open(renameReportModal, {
  reportId: report.id,
  currentName: report.name,
});

if (result.status === "renamed") {
  await renameReport({
    id: report.id,
    name: result.name,
  });
}

Diese Herangehensweise liegt dem Ansatz des Pakets @okyrychenko-dev/react-modal-manager zugrunde. Es handelt sich dabei nicht um ein Design-System oder eine UI-Komponente, sondern um einen typsicheren Vertrag zwischen Anwendungscode und Dialog-UI, der die Verwaltung modaler Abläufe vereinfacht.

Warum traditionelle Ansätze modale Zustände unübersichtlich machen

In den meisten React-Projekten beginnt die Verwaltung modaler Dialoge lokal innerhalb einer Komponente. Ein boolescher Zustand steuert, ob der Dialog angezeigt wird, und Callback-Funktionen wie onClose regeln die Schließlogik.

function ReportsPage() {
  const [isRenameOpen, setIsRenameOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsRenameOpen(true)}>Umbenennen</button>
      {isRenameOpen && (
        <RenameModal onClose={() => setIsRenameOpen(false)} />
      )}
    </>
  );
}

Doch mit wachsenden Anforderungen wird diese Struktur schnell unhandlich. Verschiedene Dialoge benötigen unterschiedliche Eingabedaten und Rückgabewerte, was zu einer Flut von Zustandsvariablen führt:

  • isRenameOpen, isDeleteOpen, isShareOpen
  • renameTarget, deleteTarget, shareTarget

Die eigentliche Herausforderung liegt nicht in der UI selbst, sondern in der Orchestrierung dieser Zustände:

  • Wo wird der modale Zustand verwaltet?
  • Wie werden typsichere Eingabedaten an den Dialog übergeben?
  • Wie wird ein typsicheres Ergebnis zurückgegeben?
  • Wie wird der Dialog außerhalb von React-Komponenten geöffnet, etwa über Tastenkombinationen oder einen Befehlspalette?
  • Wie vermeidet man Zustandslecks in Tests?

Das Problem mit schwach typisierten Promise-basierten APIs

Viele modale Bibliotheken bieten zwar Promise-basierte APIs an – etwa @ebay/nice-modal-react – doch die Rückgabetypen sind oft zu vage formuliert.

// @ebay/nice-modal-react
const result = await NiceModal.show("rename-report", data);

// result ist vom Typ 'any'
result.nme;       // Kein Fehler – Tippfehler bleibt unbemerkt
result.whatever;  // Kein Fehler – nicht vorhandene Eigenschaft
result.name;      // Funktioniert, aber TypeScript kann nicht helfen

Wenn result vom Typ any ist, kann TypeScript die Vertragsvereinbarung zwischen Aufrufer und Modal nicht überprüfen. Ein typsicheres Modal hingegen stellt einen klaren Vertrag dar:

// @okyrychenko-dev/react-modal-manager
const result = await modal.open(renameReportModal, data);

// result ist vom Typ:
// { status: "renamed"; name: string } | { status: "cancelled" }

result.nme;       // Fehler: Property 'nme' existiert nicht
result.whatever;  // Fehler: Property 'whatever' existiert nicht
result.name;      // Nur verfügbar nach Typprüfung

Der Unterschied ist entscheidend: In langlebigen Codebasen sind schwach typisierte modale Rückgaben eine häufige Quelle für stille Laufzeitfehler und unbeabsichtigte Refactoring-Probleme.

Kernziele der Bibliothek

Das Paket @okyrychenko-dev/react-modal-manager wurde mit klaren Designvorgaben entwickelt:

  • Typsichere Eingaben und Rückgaben durch TypeScript-Inferenz
  • Gekapselter modaler Zustand innerhalb eines Providers, um globale Lecks zu vermeiden
  • Austauschbarkeit der UI-Schicht (z. B. zwischen verschiedenen Design-Systemen)
  • Unterstützung für Modals sowohl innerhalb als auch außerhalb von React-Komponenten
  • Explizite Steuerung des Lebenszyklus – Öffnen, Schließen, Ablehnen, Bestätigen

Einfache Integration in React-Anwendungen

Beginnen Sie mit der Umhüllung Ihrer Anwendung durch den ModalProvider. Anschließend können Sie den useModalManager-Hook in jeder untergeordneten Komponente verwenden.

import { ModalProvider, useModalManager } from "@okyrychenko-dev/react-modal-manager";

function App() {
  return (
    <ModalProvider>
      <ReportsPage />
    </ModalProvider>
  );
}

function DeleteButton() {
  const modal = useModalManager();

  async function handleDelete() {
    const { confirmed } = await modal.confirm({
      title: "Bericht löschen?",
      description: "Diese Aktion kann nicht rückgängig gemacht werden.",
      confirmText: "Löschen",
      variant: "danger",
    });

    if (!confined) return;
    await deleteReport();
  }

  return <button onClick={handleDelete}>Löschen</button>;
}

Es gibt keine Notwendigkeit für angehobene Zustände oder Callback-Ketten. Der Ablauf liest sich sequenziell und ist leicht nachvollziehbar.

Typsichere Modals definieren

Ein Modal ist im Wesentlichen eine React-Komponente mit typsicheren Eingaben und Rückgaben. Hier ein Beispiel für ein Umbenennungs-Modal:

import {
  createModal,
  type ModalComponentProps,
} from "@okyrychenko-dev/react-modal-manager";

interface RenameReportInput {
  reportId: string;
  currentName: string;
}

type RenameReportResult =
  | { status: "renamed"; name: string }
  | { status: "cancelled" };

function RenameReportModal({
  input,
  close,
}: ModalComponentProps<RenameReportInput, RenameReportResult>) {
  const [name, setName] = useState(input.currentName);

  return (
    <dialog open>
      <h2>Bericht umbenennen</h2>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button onClick={() => close({ status: "cancelled" })}>Abbrechen</button>
      <button onClick={() => close({ status: "renamed", name })}>Umbenennen</button>
    </dialog>
  );
}

export const renameReportModal = createModal<RenameReportInput, RenameReportResult>({
  component: RenameReportModal,
});

Jeder Aufrufer erhält nun volle Typisierung:

const result = await modal.open(renameReportModal, {
  reportId: report.id,
  currentName: report.name,
});

if (result.status === "renamed") {
  await renameReport({
    id: report.id,
    name: result.name,
  });
}

TypeScript erkennt automatisch, welche Eingaben das Modal erwartet, welche Struktur für close() verwendet werden kann und wie das Ergebnis eingegrenzt wird. Ändert sich ein Feld in RenameReportResult, bricht der Compiler sofort – nicht erst zur Laufzeit.

Der ModalHandle und sein Lebenszyklus

Die Methode modal.open() gibt einen ModalHandle zurück – ein Promise mit zwei zusätzlichen Eigenschaften zur Steuerung des Lebenszyklus. Diese Struktur ermöglicht es, eine spezifische Instanz des Modals zu identifizieren und gezielt zu schließen oder abzulehnen.

Durch die Kombination aus typsicheren Eingaben, asynchroner Verarbeitung und expliziter Lebenszyklussteuerung wird die Verwaltung modaler Dialoge in React-Anwendungen deutlich robuster und wartbarer. Entwickler können sich auf die Geschäftslogik konzentrieren, während die UI-Schicht austauschbar bleibt – ein Ansatz, der besonders in großen, langlebigen Projekten langfristig Zeit und Nerven spart.

In Zukunft wird die Integration typsicherer Modals in React-Anwendungen noch weiter an Bedeutung gewinnen, da die Komplexität von Benutzeroberflächen stetig zunimmt. Bibliotheken wie @okyrychenko-dev/react-modal-manager zeigen, wie moderne Tools Entwicklern helfen können, sauberen, typsicheren Code zu schreiben – ohne Kompromisse bei Benutzerfreundlichkeit oder Funktionalität.

KI-Zusammenfassung

React uygulamalarında modallar için tip güvenliğini nasıl sağlarsınız? Promise<TResult> tabanlı modal yönetimiyle async operasyonları basitleştirin ve hata riskini azaltın.

Kommentare

00
KOMMENTAR SCHREIBEN
ID #INPLF0

0 / 1200 ZEICHEN

Menschen-Check

8 + 9 = ?

Erscheint nach redaktioneller Prüfung

Moderation · Spam-Schutz aktiv

Noch keine Kommentare. Sei der erste.