Om Dingen in Context Met Reageren

0
65

Context is momenteel een experimentele API voor het Reageren – maar binnenkort een eerste klasse van de burger! Er zijn een heleboel redenen is het interessant, maar misschien wel het meest is dat het ruimte biedt voor ouders componenten om gegevens door te geven impliciet aan hun kinderen, ongeacht hoe diep de component boom is. In andere woorden, de gegevens kunnen worden toegevoegd aan een ouder component en vervolgens elk kind kan tappen.

Zie de Pen Reageren Context Lichten door Neal Fennimore (@nealfennimore) op CodePen.

Hoewel dit vaak dat de use case voor het gebruik van iets als Redux, het is leuk om te gebruiken als u niet-complexe data management. Denk over het! We maken een aangepaste stroomafwaarts van gegevens, het beslissen welke rekwisieten worden doorgegeven en op welke niveaus. Pretty cool.

Context is groot in de gebieden waar je veel van de onderdelen die afhankelijk zijn van een enkel stuk van de gegevens, maar zijn diep van binnen het onderdeel structuur. Expliciet het passeren van elk prop aan elk van de afzonderlijke componenten kunnen vaak overweldigend en het is een stuk eenvoudiger, gewoon om de context hier.

Bijvoorbeeld, laten we eens kijken hoe we normaal aan voorbij zou gaan rekwisieten uit de boom. In dit geval, we passeren de kleur rood met behulp van rekwisieten voor elk onderdeel om te bewegen op door de beek.

klasse Ouder breidt Reageren.Onderdeel {
render(){
terug <Kind color=”red” />;
}
}

klasse Kind breidt Reageren.Onderdeel {
render(){
terug <Kleinkind color={dit.props.kleur} />
}
}

klasse Kleinkind breidt Reageren.Onderdeel {
render(){
return (
<div style={{color: met deze.props.kleur}}>
Yep, ik ben het Kleinkind
</div>
);
}
}

Wat als we nooit wilde het Kind component om de prop in de eerste plaats? Context bespaart ons hoeft te gaan door het Kind component met kleur en doorgeven rechtstreeks van de Ouder van het Kleinkind:

klasse Ouder breidt Reageren.Onderdeel {
// Laat kinderen context van het gebruik
getChildContext() {
terug {
kleur: ‘rood’
};
}

render(){
terug <Kind />;
}
}

Ouder.childContextTypes = {
kleur: PropTypes.string
};

klasse Kind breidt Reageren.Onderdeel {
render() {
// Rekwisieten is verwijderd en de context stroomt door aan Kleinkind
terug <Kleinkind />
}
}

klasse Kleinkind breidt Reageren.Onderdeel {
render() {
return (
<div style={{color: met deze.de context.kleur}}>
Yep, ik ben nog aan het Kleinkind
</div>
);
}
}

// Bloot kleur aan het Kleinkind
Kleinkind.contextTypes = {
kleur: PropTypes.string
};

Terwijl iets meer uitgebreid, de kop is het blootstellen van de kleur overal neer in het onderdeel structuur. Goed, soms…

Er is een Aantal Valkuilen

Je kunt niet altijd uw cake hebben en het ook eten, en de context in de huidige vorm, is geen uitzondering. Er zijn een aantal onderliggende problemen die je zal meer dan waarschijnlijk in contact komen met als je uiteindelijk met behulp van context voor alle, maar de meest eenvoudige gevallen.

Context is ideaal voor gebruik op een eerste render. Het bijwerken van de context op de vlieg? Niet zo veel. Een gemeenschappelijk probleem met context is dat de context veranderingen niet altijd weerspiegeld in een component.

Laten we ontleden deze valkuilen in meer detail.

Gotcha 1: Het Gebruik Van Zuivere Componenten

Context is het moeilijk bij het gebruik van PureComponent omdat standaard niet uitvoeren van een ondiepe vergelijk standaard voorzien van context. Ondiepe vergelijk met PureComponent is testen voor de vraag of de waarden van het object zijn ten strengste gelijk. Als ze niet zijn, dan (en alleen dan) zal de component update. Maar aangezien de context, niet gecontroleerd, goed… er gebeurt niets.

Zie de Pen Reageren Context Lichten met PureComponents door Neal Fennimore (@nealfennimore) op CodePen.

Gotcha 2: Moet Component Update? Misschien.

Context ook geen update uitvoeren als een onderdeel shouldComponentUpdate geeft onwaar als resultaat. Als u een aangepaste shouldComponentUpdate methode, dan zul je je ook moet nemen van de context in overweging. Om te zorgen dat updates met context, we konden update elke individuele component met een aangepaste shouldComponentUpdate dat ziet er zo uit.

importeren shallowEqual van ‘fbjs/lib/shallowEqual’;

klasse ComponentThatNeedsColorContext breidt Reageren.PureComponent {
// nextContext-show zal de kleur van zodra wij de betaling ComponentThatNeedsColorContext.contextTypes
// LET op: het Doen van de hieronder geven een console fout komen te reageren v16.1.1
shouldComponentUpdate(nextProps, nextState, nextContext -) {
terug !shallowEqual(deze.rekwisieten, nextProps) || !shallowEqual(deze.staat, nextState) || !shallowEqual(deze.context, nextContext -);
}
}

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

Echter, dit is niet op te lossen het probleem van een tussenpersoon PureComponent tussen de ouder en het kind blokkeren context updates. Dit betekent dat elke PureComponent tussen de ouder en het kind zou moeten hebben contextTypes gedefinieerd, en ze zou ook nodig zijn om een bijgewerkte shouldComponentUpdate methode. En op dit punt, dat is veel werk voor weinig krijgen.

Betere Aanpak van de Valkuilen

Gelukkig hebben we een aantal manieren om te werken rond de valkuilen.

Aanpak 1: het Gebruik van een Hogere-Orde Component

Een Hogere-Orde Component kan lezen van de context en het doorgeven van de benodigde waarden op naar de volgende component als een prop.

importeren Reageren van ‘reageren’;

const withColor = (WrappedComponent) => {
klasse ColorHOC breidt Reageren.Onderdeel {
render() {
const { color } = dit.context;
terug <WrappedComponent style={{color: kleur}} {…dit.props} />
}
}

ColorHOC.contextTypes = {
kleur: Reageren.PropTypes.string
};

terug ColorHOC;
};

export const Knop = (rekwisieten)=> knop <{…props}>Knop</button>

// ColoredButton zal maken met wat kleur, is op dit moment in verband met een stijl prop
export const ColoredButton = withColor( Knop );

Zie de Pen Reageren Context Lichten met HOC door Neal Fennimore (@nealfennimore) op CodePen.

Aanpak 2: Gebruik Het Renderen Van Rekwisieten

Het renderen van Rekwisieten kunnen wij gebruik maken van rekwisieten te delen code tussen de twee componenten.

klasse App breidt Reageren.Onderdeel {
getChildContext() {
terug {
kleur: ‘rood’
}
}

render() {
terug < – Knop />
}
}

App.childContextTypes = {
kleur: Reageren.PropTypes.string
}

// Hook ‘Kleur’ in ‘App’ context
klasse Kleur uitstrekt Reageren.Onderdeel {
render() {
retourneren.props.render(deze.de context.kleur);
}
}

Kleur.contextTypes = {
kleur: Reageren.PropTypes.string
}

de Knop klasse breidt Reageren.Onderdeel {
render() {
return (
<button type=”button”>
{/* Return gekleurde tekst in Knop */}
<Kleur render={ kleur => (
<Text color={kleur} text=”Knop ” Text” />
) } />
</button>
)
}
}

klas Tekst uitgebreid Reageren.Onderdeel {
render(){
return (

{dit.props.tekst}

)
}
}

Tekst.propTypes = {
tekst: Reageren.PropTypes.string,
kleur: Reageren.PropTypes.string,
}</Color></button>
Benadering 3: Dependency Injection

Een derde manier kunnen we werken rond deze valkuilen is gebruik te maken van Dependency Injection te beperken in het kader van de API en onderdelen in te schrijven als dat nodig is.

De Nieuwe Context

De nieuwe manier van het gebruik van context, die momenteel gepland voor de volgende kleine versie van Reageren (16.3), heeft de voordelen van beter leesbaar en makkelijker om te schrijven zonder de “valkuilen” van de vorige versies. We hebben nu een nieuwe methode genaamd createContext, waarin een nieuwe context en geeft zowel een Aanbieder en Consument.

De Aanbieder stelt een kader dat alle sub-componenten kunt aansluiten. Het is aangesloten via een Consument die gebruik maakt van een render prop. Het eerste argument van die render prop functie, is de waarde die we hebben gegeven aan de Provider. Door het bijwerken van de waarde binnen de Provider, alle consumenten wordt bijgewerkt met de nieuwe waarde.

Een bijkomend voordeel van het gebruik van de nieuwe context, we hebben niet langer te gebruiken childContextTypes, getChildContext, en contextTypes.

const ColorContext = Reageren.createContext(‘kleur’);
klasse ColorProvider breidt Reageren.Onderdeel {
render(){
return (
<ColorContext.Provider waarde={‘rood’}>
{ dit.props.kinderen }
</ColorContext.Provider>
)
}
}

klasse Ouder breidt Reageren.Onderdeel {
render(){
// Wrap ‘Kind’ met onze provider kleur
return (
<ColorProvider>
<Kind />
</ColorProvider>
);
}
}

klasse Kind breidt Reageren.Onderdeel {
render(){
terug <Kleinkind />
}
}

klasse Kleinkind breidt Reageren.Onderdeel {
render(){
// Verbruiken onze context en doorgeven van de kleur in de stijl-kenmerk
return (
<ColorContext.Consument>
{/* ‘kleur’ is de waarde van onze Provider */}
{
color => (
<div style={{color: kleur}}>
Yep, ik ben nog aan het Kleinkind
</div>
)
}
</ColorContext.Consument>
);
}
}

Aparte Contexten

Omdat we hebben meer controle in hoe stellen we de context en de onderdelen zijn toegestaan gebruik te maken, kunnen we individueel wrap componenten met een verschillende contexten, ook al wonen zij in dezelfde component. We kunnen dit zien in het volgende voorbeeld, waarbij het gebruik van de LightProvider tweemaal, geven we de twee onderdelen een aparte context.

Zie de Pen Reageren Context Lichten met nieuwe Context door Neal Fennimore (@nealfennimore) op CodePen.

Conclusie

Context is een krachtige API, maar het is ook zeer gemakkelijk te gebruiken is onjuist. Er zijn ook een paar kanttekeningen te gebruiken, en het kan heel moeilijk zijn om erachter te komen kwesties als onderdelen bederven. Terwijl een Hogere Orde Componenten en dependency injection en alternatieven bieden voor de meeste gevallen, de context kan voordelig gebruikt worden in afgelegen gedeelten van de code base.

Met de volgende context hoewel we ons niet langer zorgen te maken over de valkuilen die we hadden met de vorige versie. Het verwijdert hoeft te definiëren contextTypes op afzonderlijke onderdelen en opent de mogelijkheden voor het definiëren van nieuwe contexten in een herbruikbare manier.