Lernen Sie, in 5 Minuten auf den Kontext zu reagieren - Ein Tutorial für Anfänger

Die Kontext-API von React ist für viele zum bevorzugten Tool für die Statusverwaltung geworden und ersetzt häufig Redux insgesamt. In diesem kurzen 5-minütigen Tutorial sehen Sie eine Einführung in den Kontext und dessen Verwendung!

Wenn Sie eine angemessene Einführung in dieses Thema wünschen, können Sie sich auf die Warteliste für meinen bevorstehenden React-Kurs für Fortgeschrittene setzen. Wenn Sie noch Anfänger sind, lesen Sie meinen kostenlosen Einführungskurs zu React.

Betrachten Sie diesen Baum, in dem die unteren Felder separate Komponenten darstellen:

Komponentenbaum

Wir können den unteren Komponenten problemlos Status hinzufügen, aber bis jetzt bestand die einzige Möglichkeit, Daten an das Geschwister einer Komponente zu übergeben, darin, den Status an eine höhere Komponente zu verschieben und ihn dann über Requisiten wieder an das Geschwister weiterzugeben.

Daten über Requisiten weitergeben

Wenn wir später herausfinden, dass das Geschwister der Komponente mit Status auch die Daten benötigt, müssen wir den Status wieder anheben und wieder weitergeben:

Weitergabe des Status durch mehrere Ebenen

Während diese Lösung funktioniert, beginnen Probleme, wenn eine Komponente in einem anderen Zweig die Daten benötigt:

Weiter entfernte Komponenten erfordern Daten

In diesem Fall müssen wir den Status von der obersten Ebene der Anwendung über alle Zwischenkomponenten an die übergeben, die die Daten unten benötigt, obwohl die Zwischenebenen sie nicht benötigen. Dieser langwierige und zeitaufwändige Vorgang wird als Propellerbohren bezeichnet .

Propellerbohren

Hier kommt die Kontext-API ins Spiel. Sie bietet eine Möglichkeit, Daten über ein Provider-Consumer-Paar durch den Komponentenbaum zu leiten, ohne Requisiten durch jede Ebene weitergeben zu müssen. Stellen Sie sich das als die Komponenten vor, die Catch with Data spielen - die Zwischenkomponenten "wissen" möglicherweise nicht einmal, dass etwas passiert:

Kontext in Aktion

Um dies zu demonstrieren, werden wir dieses funky (und super nützliche) Tag-zu-Nacht-Schaltbild erstellen.

Wenn Sie den vollständigen Code sehen möchten, lesen Sie unbedingt den Scrimba-Spielplatz für diesen Artikel.

Kontext erstellen

Zunächst erstellen wir einen neuen Kontext. Da wir möchten, dass die gesamte App darauf zugreifen kann, gehen wir zu index.jsund wickeln die App ein ThemeContext.Provider.

Wir geben die valueRequisite auch an unseren Provider weiter. Dies enthält die Daten, die wir speichern möchten. Im Moment codieren wir nur fest ein 'Day'.

import React from "react"; import ReactDOM from "react-dom"; import ThemeContext from "./themeContext"; import App from "./App"; ReactDOM.render(   , document.getElementById("root") ); 

Kontext mit contextType konsumieren

Derzeit senden App.jswir die Komponente einfach zurück .

import React from "react"; import Image from "./Image"; class App extends React.Component { render() { return ( ); } } export default App; 

Unser Ziel ist es, den Kontext zu verwenden, um die Klassennamen Image.jsvon Dayauf zu wechseln Night, je nachdem, welches Bild wir rendern möchten. Zu diesem ContextTypeZweck fügen wir unserer Komponente eine statische Eigenschaft mit dem Namen hinzu und verwenden dann die Zeichenfolgeninterpolation, um sie den Klassennamen in der Komponente hinzuzufügen .

Jetzt enthalten die Klassennamen die Zeichenfolge aus der valueRequisite. Hinweis: Ich bin ThemeContextin eine eigene Datei umgezogen , um einen Fehler zu vermeiden.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; class Image extends React.Component { render() { const theme = this.context; return ( ); } } Image.contextType = ThemeContext; export default Image; 

Context.Consumer

Leider funktioniert dieser Ansatz nur mit klassenbasierten Komponenten. Wenn Sie bereits von Hooks in React erfahren haben, wissen Sie, dass wir heutzutage fast alles mit funktionalen Komponenten tun können. Aus gutem Grund sollten wir unsere Komponenten in funktionale Komponenten umwandeln und dann ThemeContext.ConsumerKomponenten verwenden, um Informationen über die App zu übertragen.

Dies geschieht, indem wir unsere Elemente in eine Instanz von und innerhalb dieser (wohin childrengehen) einschließen und eine Funktion bereitstellen, die die Elemente zurückgibt. Dies verwendet das Muster "Render Prop", bei dem wir als untergeordnetes Element eine reguläre Funktion bereitstellen, die JSX zum Rendern zurückgibt.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; function Image(props) { // We don't need this anymore // const theme = this.context return (  {theme => ( )}  ); } // We don't need this anymore // Image.contextType = ThemeContext; export default Image; 

Hinweis: Wir müssen die Komponente auch einpacken. Dadurch können wir der Schaltfläche später Funktionen hinzufügen.

import React from "react"; import ThemeContext from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Kontextanbieter extrahieren

Wir geben derzeit einen fest codierten Wert über den Anbieter weiter. Unser Ziel ist es jedoch, mit unserer Schaltfläche zwischen Tag und Nacht zu wechseln.

Dazu muss unser Provider in eine separate Datei verschoben und in eine eigene Komponente eingefügt werden, in diesem Fall aufgerufen ThemeContextProvider.

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); class ThemeContextProvider extends Component { render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Hinweis: Die value-Eigenschaft wird jetzt in der neuen Datei ThemeContext.js behandelt und sollte daher aus index.js entfernt werden.

Kontext ändern

Um die Schaltfläche zu verkabeln, fügen wir zunächst den Status hinzu zu ThemeContextProvider:

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); // Note: You could also use hooks to provide state and convert this into a functional component. class ThemeContextProvider extends Component { state = { theme: "Day" }; render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Als nächstes fügen wir eine Methode zum Umschalten zwischen Tag und Nacht hinzu:

toggleTheme = () => { this.setState(prevState => { return { theme: prevState.theme === "Day" ? "Night" : "Day" }; }); }; 

Jetzt ändern wir unsere valueEigenschaft in, this.state.themesodass die Informationen aus dem Status zurückgegeben werden.

 render() { return {this.props.children}; } } 

Next, we change value to an object containing {theme: this.state.theme, toggleTheme: this.toggleTheme}, and update all the places where we use a single value to look for theme in an object. This means that every theme becomes context and every reference to theme as value becomes context.theme.

Finally, we tell the button to listen for the onClick event and then fire context.toggleTheme - this updates the Consumers which are using the state from the Provider. The code for the button looks like this:

import React from "react"; import { ThemeContextConsumer } from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Our button now switches the image between night and day in one click!

Context caveats

Like all good things in code, there are some caveats to using Context:

  • Don't use Context to avoid drilling props down just one or two layers. Context is great for managing state which is needed by large portions of an application. However, prop drilling is faster if you are just passing info down a couple of layers.

  • Avoid using Context to save state that should be kept locally. So if you need to save a user's form inputs, for example, use local state and not Context.

  • Always wrap the Provider around the lowest possible common parent in the tree - not the app's highest-level component. No need for overkill.

  • Lastly, if you pass an object as your value prop, monitor performance and refactor as necessary. This probably won't be needed unless a drop in performance is noticeable.

Wrap up

Dieses Beispiel ist ziemlich einfach und es wäre wahrscheinlich einfacher, den Status in die App zu setzen und ihn über Requisiten weiterzugeben. Es zeigt jedoch hoffentlich die Leistungsfähigkeit von Verbrauchern, die unabhängig von den darüber liegenden Komponenten im Baum auf Daten zugreifen können.

Um mehr über React Context und andere großartige Funktionen von React zu erfahren, können Sie sich auf die Warteliste für meinen bevorstehenden fortgeschrittenen React-Kurs setzen. Oder wenn Sie auf der Suche nach einem anfängerfreundlicheren sind, können Sie sich meinen kostenlosen Einführungskurs zu React ansehen.

Viel Spaß beim Codieren :)