Heim >Web-Frontend >js-Tutorial >Erläutern des bereichsbezogenen Kontexts in React anhand eines Beispiels

Erläutern des bereichsbezogenen Kontexts in React anhand eines Beispiels

Barbara Streisand
Barbara StreisandOriginal
2024-12-26 09:11:10750Durchsuche

Explaining Scoped Context in React with example

React Context ist eine globale Variable

In Javascript haben Variablen ihren Gültigkeitsbereich innerhalb von Funktionsdefinitionen.

Erläutern des bereichsbezogenen Kontexts in React anhand von Beispielen

React Context wird oft als ein Mechanismus zur Verwaltung des globalen Status beschrieben, der als gemeinsam genutzte Variable fungiert, auf die über einen React-Komponentenbaum zugegriffen werden kann. Obwohl diese Beschreibung korrekt ist, vereinfacht sie die Funktionen von Context zu stark. In diesem Artikel befassen wir uns damit, wie Sie den Kontext effektiv festlegen und sicherstellen, dass er nur dort verwendet wird, wo er benötigt wird, und unnötige erneute Renderings vermeiden.

Was ist Reaktionskontext?

React Context bietet eine Möglichkeit, Daten durch den Komponentenbaum zu leiten, ohne Requisiten auf jeder Ebene manuell übergeben zu müssen. Es wird mit React.createContext erstellt und besteht aus einem Provider- und Consumer-Paar. Eine Provider-Komponente stellt den Wert bereit, und jede mit dem Consumer- oder useContext-Hook umschlossene Komponente kann darauf zugreifen.

Hier ist ein einfaches Beispiel:

import React, { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return <ThemedButton />;
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button>{`Theme: ${theme}`}</button>;
}

export default App;

In diesem Beispiel kann ThemedButton auf den von ThemeContext.Provider bereitgestellten Designwert zugreifen, ohne Requisiten explizit über die Symbolleiste zu übergeben.

Warum bereichsbezogener Kontext?

Der Kontext ist zwar leistungsstark, seine wahllose Verwendung kann jedoch zu Leistungsproblemen führen. Wenn sich der von einem Context.Provider bereitgestellte Wert ändert, werden alle Komponenten, die diesen Kontext nutzen, neu gerendert. In komplexen Anwendungen kann dies dazu führen, dass nicht verwandte Komponenten unnötig neu gerendert werden müssen.

Scoped Context bezieht sich auf die Praxis, die Verwendung von Context nur auf die Teile des Komponentenbaums zu beschränken, die ihn tatsächlich benötigen. Dieser Ansatz trägt dazu bei, die Leistung aufrechtzuerhalten und die Komponentenstruktur sauber und verständlich zu halten.

Herausforderungen bei Verbundkomponenten

Berücksichtigen Sie Szenarien mit zusammengesetzten Komponenten, wie sie beispielsweise von Bibliotheken wie Radix Primitives bereitgestellt werden. Diese Komponenten verwenden Kontext häufig intern, um Status und Interaktionen zu verwalten. Allerdings können Probleme auftreten, wenn ähnliche Komponenten zusammengefügt werden, was zu Kontextkollisionen führen kann.

Beispiel mit Radix-Primitiven

Radix Primitives bietet hochgradig zusammensetzbare APIs zum Erstellen barrierefreier Komponenten. Hier ist ein Beispiel:

<AlertDialog.Root>
  <Dialog.Root>
    <Dialog.Trigger />
    <Dialog.Content>
      <AlertDialog.Trigger /> {/* note the alert trigger in dialog content */}
    </Dialog.Content>
  </Dialog.Root>

  <AlertDialog.Content />
</AlertDialog.Root>

Hier tritt ein Problem auf, da AlertDialog eine Zusammensetzung von Dialog mit zusätzlichen Funktionen ist, um die AlertDialog-Anforderungen zu erfüllen. Dies bedeutet, dass AlertDialog.Root auch ein Dialog.Root ist und daher sowohl DialogContext als auch AlertDialogContext bereitstellt.

In diesem Setup ruft der AlertDialog.Trigger (der auch ein Dialog.Trigger ist) möglicherweise den falschen Kontext über useContext(DialogContext) ab und erhält am Ende den Kontext von Dialog.Root statt von AlertDialog.Root. Infolgedessen könnte das Klicken auf den AlertDialog.Trigger den Dialog.Content umschalten, anstatt sich wie beabsichtigt zu verhalten.

Bereichsbezogene Kontextlösung

Um solche Probleme zu verhindern, verwendet Radix Primitives einen bereichsbezogenen Kontext. Der Bereichskontext stellt sicher, dass AlertDialog.Trigger nur mit AlertDialog-Teilen interagiert und nicht versehentlich Kontext von einer ähnlich zusammengesetzten Komponente abruft. Dies wird erreicht, indem intern ein neuer Kontext erstellt und über eine benutzerdefinierte Requisite wie __scopeDialog an die Dialog-Komponente übergeben wird. Die Dialog-Komponente verwendet dann diesen bereichsbezogenen Kontext in ihren useContext-Aufrufen und stellt so die Isolation sicher.

Quellcode von radix ui github repo:

https://github.com/radix-ui/primitives/blob/dae8ef4920b45f736e2574abf23676efab103645/packages/react/dialog/src/Dialog.tsx#L69

Hier ist eine Abstraktion, wie bereichsbezogene Kontexte in der Radix-Benutzeroberfläche funktionieren:

  1. Bereichserstellung: Ein Dienstprogramm „createScope“ generiert einen eindeutigen Namespace für jede Komponente oder zusammengesetzte Komponente. Dadurch wird sichergestellt, dass jeder Satz von Kontexten isoliert ist und nicht mit anderen in Konflikt steht.

    import React, { createContext, useContext } from "react";
    
    const ThemeContext = createContext("light");
    
    function App() {
      return (
        <ThemeContext.Provider value="dark">
          <Toolbar />
        </ThemeContext.Provider>
      );
    }
    
    function Toolbar() {
      return <ThemedButton />;
    }
    
    function ThemedButton() {
      const theme = useContext(ThemeContext);
      return <button>{`Theme: ${theme}`}</button>;
    }
    
    export default App;
    
  2. Bereichsbezogene Anbieter: Beim Erstellen von Kontexten sind sie an den Bereich gebunden. Dadurch werden Anbieter und Verbraucher an denselben Namensraum gebunden.

    <AlertDialog.Root>
      <Dialog.Root>
        <Dialog.Trigger />
        <Dialog.Content>
          <AlertDialog.Trigger /> {/* note the alert trigger in dialog content */}
        </Dialog.Content>
      </Dialog.Root>
    
      <AlertDialog.Content />
    </AlertDialog.Root>
    
  3. Verbraucherisolation: Bereichsbezogene Hooks wie useDialogScope stellen sicher, dass Verbraucher nur auf den Kontext aus ihrem vorgesehenen Bereich zugreifen.

    import { createScope } from '@radix-ui/react-context';
    
    const [createDialogContext, useDialogScope] = createScope('Dialog');
    

Vorteile des Scoped Context

  • Verhinderung von Kontextkollisionen: Durch die Festlegung von Kontexten können Komponenten wie AlertDialog.Trigger immer ihren zugehörigen Kontext (AlertDialogContext) finden, auch wenn sie in anderen Kontexten verschachtelt sind.

  • Flexible Komposition: Bereichsbezogene Kontexte ermöglichen eine flexible und sichere Komposition von Komponenten und stellen sicher, dass Interaktionen vorhersehbar bleiben.

  • Wiederverwendbarkeit: Entwickler können generische Komponenten (z. B. Dialog.Trigger) ohne Änderungen in verschiedenen Bereichen wiederverwenden.

Wie es auf das Beispiel anwendbar ist

In Ihrem Beispiel:

  • AlertDialog.Root erstellt einen bereichsbezogenen AlertDialogContext, der seinen Status und seine Interaktionen kapselt.

  • Verschachtelte Dialog.Root und AlertDialog.Trigger koexistieren ohne Konflikte, da jeder auf seinen jeweiligen Gültigkeitsbereich verweist.

  • Dieses Entwurfsmuster ist ein Schlüsselmerkmal der Radix-Benutzeroberfläche und stellt sicher, dass komplexe Komponentenhierarchien nahtlos und ohne unbeabsichtigtes Verhalten funktionieren.

Referenzen:

  1. https://dev.to/romaintrotard/use-context-selector-demystified-4f8e

  2. https://github.com/radix-ui/primitives

  3. https://react.dev/reference/react/createContext

Das obige ist der detaillierte Inhalt vonErläutern des bereichsbezogenen Kontexts in React anhand eines Beispiels. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn