React Context ist eine globale Variable
In Javascript haben Variablen ihren Gültigkeitsbereich innerhalb von Funktionsdefinitionen.
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.
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.
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.
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.
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.
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
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;
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>
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');
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.
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.
https://dev.to/romaintrotard/use-context-selector-demystified-4f8e
https://github.com/radix-ui/primitives
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!