Putting Dinge in Zusammenhang Mit Reagieren

0
42

Kontext ist derzeit eine experimentelle API für Reagieren – aber bald zu einem erste-Klasse-Bürger! Es gibt eine Menge Gründe, es ist interessant, aber vielleicht die ist, dass es eine übergeordnete Komponenten, die zum übergeben von Daten implizit, um Ihre Kinder, egal wie tief die Komponente Baum ist. In anderen Worten, Daten können Hinzugefügt werden zu einer übergeordneten Komponente und anschließend jedem Kind erschließen.

Finden Sie den Stift Reagieren Kontext Lichter von Neal Fennimore (@nealfennimore) auf CodePen.

Dies ist zwar oft der Fall für Sie so etwas wie Redux, es ist schön zu verwenden, wenn Sie brauchen keine komplexen Daten-management. Denke, über, die! Wir erstellen ein individuelles downstream von Daten, zu entscheiden, welche Requisiten übergeben werden und in welchen Mengen. Ziemlich cool.

Kontext ist ideal in Bereichen, wo Sie haben eine Menge von Komponenten, die abhängig von einem einzigen Stück von Daten, sondern sind tief in der Komponentenstruktur. Explizit übergeben jede requisite, jede einzelne Komponente kann oft überwältigend sein, und es ist viel einfacher, nur um Kontext hier.

Zum Beispiel, lassen Sie uns überlegen, wie wir normalerweise pass Requisiten unten in der Struktur. In diesem Fall sind wir vorbei an der Farbe rot mit Requisiten auf jede Komponente, um ihn zu bewegen auf den Strom hinab.

Klasse Elternteils erstreckt Reagieren.Komponente {
render(){
zurück <Kind color=”red” />;
}
}

class Kind extends Reagieren.Komponente {
render(){
zurück <Enkel color={das.Requisiten.Farbe} />
}
}

Klasse Enkelkind erstreckt Reagieren.Komponente {
render(){
return (
<div style={{color:.Requisiten.Farbe}}>
Yep, ich bin der Enkel
</div>
);
}
}

Was, wenn wir nie wollten, die Kind-Komponente prop in Erster Linie? Kontext erspart uns den Umweg durch die Untergeordnete Komponente mit Farbe und übergeben Sie es direkt von den Eltern an die Enkel:

Klasse Elternteils erstreckt Reagieren.Komponente {
// Lassen Sie Ihre Kinder verwenden Kontext
getChildContext() {
return {
Farbe: ‘rot’
};
}

render(){
zurück <Child />;
}
}

Eltern.childContextTypes = {
Farbe: PropTypes.string
};

class Kind extends Reagieren.Komponente {
render() {
// Requisiten entfernt wird, und der Kontext, fließt durch Enkel
zurück <Enkel />
}
}

Klasse Enkelkind erstreckt Reagieren.Komponente {
render() {
return (
<div style={{color:.Kontext.Farbe}}>
Yep, ich bin immer noch der Enkel
</div>
);
}
}

// Setzen der Farbe auf die Enkel
Ein Enkelkind.contextTypes = {
Farbe: PropTypes.string
};

Während etwas mehr “verbose”, ” der Kopf setzt die Farbe, die irgendwo unten in der Komponentenstruktur. Gut, manchmal…

Es gibt Einige Fallstricke

Sie können nicht immer Ihren Kuchen haben und ihn auch Essen, und der Kontext, in seiner aktuellen form ist keine Ausnahme. Es gibt ein paar zugrunde liegenden Probleme, werden Sie mehr als wahrscheinlich in Kontakt kommen, wenn Sie am Ende mit Rahmen für alle, aber die einfachsten Fälle.

Rahmen ist ideal für den Einsatz auf einem ersten render. Aktualisierung der Kontext-on-the-fly? Nicht so viel. Ein häufiges Problem mit Kontext Kontext Veränderungen sind nicht immer spiegelt sich in einer Komponente.

Let ‘ s sezieren diese Punkte im detail.

Punkt 1: Unter Verwendung Der Reinen Komponenten

Kontext ist schwer, wenn es mit PureComponent da es standardmäßig nicht ausführen, flachen diff standardmäßig mit Kontext. Flache diff mit PureComponent ist die Prüfung, ob die Werte des Objekts sind gleich streng. Wenn Sie nicht sind, dann (und nur dann) wird die Komponente update. Aber da der Kontext wird nicht geprüft, naja… nix passiert.

Finden Sie den Stift Reagieren Kontext beleuchtet mit PureComponents von Neal Fennimore (@nealfennimore) auf CodePen.

Punkt 2: Soll-Komponente Zu Aktualisieren? Vielleicht.

Kontext auch nicht aktualisieren, wenn eine Komponente shouldComponentUpdate gibt false zurück. Wenn Sie eine benutzerdefinierte shouldComponentUpdate-Methode, dann müssen Sie auch nehmen, den Kontext zu berücksichtigen. Zum aktivieren der updates mit Kontext, könnten wir aktualisieren jede einzelne Komponente mit einem benutzerdefinierten shouldComponentUpdate, die wie folgt aussieht.

import shallowEqual von ‘fbjs/lib/shallowEqual’;

Klasse ComponentThatNeedsColorContext erstreckt Reagieren.PureComponent {
// nextContext-zeigen Farbe, sobald wir gelten ComponentThatNeedsColorContext.contextTypes
// HINWEIS: Dabei den unten zeigen eine Konsole Fehler reagieren v16.1.1
shouldComponentUpdate(nextProps, nextState, nextContext -) {
zurück !shallowEqual(dies.Requisiten, nextProps) || !shallowEqual(dies.state, nextState) || !shallowEqual(dies.Kontext, nextContext -);
}
}

ComponentThatNeedsColorContext.contextTypes = {
Farbe: PropTypes.string
};

Allerdings bedeutet dies nicht lösen das Problem der Vermittler PureComponent zwischen Eltern und Kind blockieren Kontext updates. Dies bedeutet, dass jedes PureComponent zwischen Eltern und Kind braucht, um contextTypes definiert, und Sie würden auch brauchen, um eine aktualisierte shouldComponentUpdate Methode. Und an diesem Punkt, das ist viel Arbeit für wenig Gewinn.

Bessere Ansätze, um die Fallstricke

Zum Glück haben wir einige Möglichkeiten zum umgehen der Fallstricke.

Methode 1: Verwenden Sie eine Höhere Order-Komponente

Eine Höhere Order-Komponente Lesen kann aus dem Kontext, und übergeben Sie die benötigten Werte an die nächste Komponente, die als requisite.

importieren Reagieren von ‘reagieren’;

const withColor = (WrappedComponent) => {
Klasse ColorHOC erstreckt Reagieren.Komponente {
render() {
const { color } =.Kontext;
zurück <WrappedComponent style={{color: color}} {…this.Requisiten} />
}
}

ColorHOC.contextTypes = {
Farbe: Reagieren.PropTypes.string
};

zurück ColorHOC;
};

export-Taste const = (Requisiten)=> <button {…props}>Button</button>

// ColoredButton machen wird mit dem, was Farbe ist derzeit in Zusammenhang mit einem Stil, prop
export const ColoredButton = withColor( Button );

Finden Sie den Stift Reagieren Kontext beleuchtet mit HOC von Neal Fennimore (@nealfennimore) auf CodePen.

Ansatz 2: Verwendung Render-Requisiten

Render-Requisiten, die es uns ermöglichen, verwenden Requisiten, um code gemeinsam zu nutzen, die zwischen zwei Komponenten.

Klasse App erweitert Reagieren.Komponente {
getChildContext() {
return {
Farbe: ‘rot’
}
}

render() {
return < – Taste />
}
}

App.childContextTypes = {
Farbe: Reagieren.PropTypes.string
}

// Hook ‘Farbe’ in ‘App’ – Kontext
class Farbe extends Reagieren.Komponente {
render() {
wieder dieses.Requisiten.Rendern(dies.Kontext.Farbe);
}
}

Farbe.contextTypes = {
Farbe: Reagieren.PropTypes.string
}

Klasse Button erweitert Reagieren.Komponente {
render() {
return (
<button type=”button”>
{/* Return farbigen text im Button */}
<Color render={ Farbe => (
<Text color={color}, text=”Button-Text” />
) } />
</button>
)
}
}

class Text extends Reagieren.Komponente {
render(){
return (

{dies.Requisiten.text}

)
}
}

Text.propTypes = {
text: Reagieren.PropTypes.string,
Farbe: Reagieren.PropTypes.string,
}</Color></button>
Ansatz 3: Dependency Injection

Eine Dritte Art, wie wir arbeiten können, um diese Probleme ist die Verwendung von Dependency Injection zu begrenzen, die Kontext-API und ermöglichen, Komponenten zu abonnieren wie nötig.

Der Neue Kontext

Die neue Art der Verwendung von Rahmen, die derzeit geplant für die nächste minor-release zu Reagieren (16.3), hat die Vorteile des seins mehr lesbar und einfacher zu schreiben, ohne die “Fallstricke” aus früheren Versionen. Wir haben jetzt eine neue Methode namens createContext definiert einen neuen Kontext und gibt sowohl die Anbieter und Verbraucher.

Der Anbieter stellt den Kontext, dass alle sub-Komponenten einbinden können. Es ist völlig in über Verbraucher, die nutzt ein render prop. Das erste argument, dass render prop-Funktion, ist der Wert, den wir gegeben haben, der Anbieter. Durch die Aktualisierung wird der Wert innerhalb der Anbieter, alle Verbraucher werden aktualisiert, um den neuen Wert.

Als Nebeneffekt ergibt sich mit der Verwendung des neuen Zusammenhang, wir müssen nicht mehr childContextTypes, getChildContext, und contextTypes.

const ColorContext = Reagieren.createContext(‘Farbe’);
Klasse ColorProvider erstreckt Reagieren.Komponente {
render(){
return (
<ColorContext.Anbieter value={‘rot’}>
{ dies.Requisiten.Kinder }
</ColorContext.Provider ->
)
}
}

Klasse Elternteils erstreckt Reagieren.Komponente {
render(){
// Wrap ‘Kind’ mit unserer Farb-Anbieter
return (
<ColorProvider>
<Child />
</ColorProvider>
);
}
}

class Kind extends Reagieren.Komponente {
render(){
zurück <Enkel />
}
}

Klasse Enkelkind erstreckt Reagieren.Komponente {
render(){
// Verbrauchen unsere Rahmen und pass die Farbe in das style-Attribut
return (
<ColorContext.Verbraucher>
{/* ‘Farbe’ ist der Wert, der von unserem Provider */}
{
Farbe => (
<div style={{color: color}}>
Yep, ich bin immer noch der Enkel
</div>
)
}
</ColorContext.Verbraucher>
);
}
}

Separate Kontexte

Da wir eine genauere Kontrolle, wie setzen wir den Kontext und auf welche Bauteile sind erlaubt, es zu benutzen, können wir individuell wickeln Komponenten mit unterschiedlichen Kontexten, auch wenn Sie Leben in der gleichen Komponente. Wir können sehen, dass dies im nächsten Beispiel, wobei mit der LightProvider zweimal, wir können die zwei Komponenten, einem separaten Kontext.

Finden Sie den Stift Reagieren Rahmen Leuchtet mit den neuen Kontext von Neal Fennimore (@nealfennimore) auf CodePen.

Fazit

Der Kontext ist ein leistungsstarkes API, aber es ist auch sehr einfach zu verwenden ist falsch. Es gibt auch ein paar Vorsichtsmaßnahmen, um es zu benutzen, und es kann sehr hart sein, um herauszufinden, Probleme bei der Komponenten schief gehen. Während Höher-Bestellung von Komponenten-und dependency injection-alternativen für die meisten Fälle, Kontext eingesetzt werden, vorteilhaft in isolierte Teile Ihrer code-Basis.

Mit dem nächsten Kontext, wenn wir uns keine sorgen mehr um die Punkte, die wir mit der vorherigen version. Es entfernt zu definieren, contextTypes auf einzelne Komponenten und eröffnet die Möglichkeit der Festlegung von neuen zusammenhängen in einer wiederverwendbaren Art und Weise.