Å sette Ting i Sammenheng Med Reagerer

0
34

Kontekst er i dag en eksperimentell API for å Reagere – men snart å være en first class citizen! Det er mange grunner til at det er interessant, men kanskje mest er at det gjør det mulig for foreldre komponenter for å overføre data implisitt til sine barn, uansett hvor dypt komponent treet er. Med andre ord, data kan bli lagt til et overordnet komponent og så noen barn kan tappe inn i det.

Se Penn Reagere Sammenheng Lys av Neal Fennimore (@nealfennimore) på CodePen.

Mens dette er ofte use case for å bruke noe som Redux, det er fint å bruke hvis du ikke trenger komplekse data management. Tenk på det! Vi opprette en egendefinert nedstrøms av data, bestemmer hvilke rekvisitter er gått, og på hvilke nivåer. Ganske kult.

Kontekst er stor i områder hvor du har mange komponenter som er avhengige av en enkelt del av data, men er dypt inne i komponenten treet. Eksplisitt passerer hver prop til hver enkelt komponent kan ofte være overveldende, og det er mye lettere bare å bruke en sammenheng her.

For eksempel, la oss vurdere hvordan vi normalt ville gå rekvisitter ned treet. I dette tilfellet, vi passerer fargen rød som bruker rekvisitter på hver komponent for å flytte den ned på strømmen.

klasse Foreldre strekker seg til å Reagere.Komponent {
render(){
retur <Barnet color=”red” />;
}
}

klasse Barnet strekker seg til å Reagere.Komponent {
render(){
retur <Barnebarn color={dette.rekvisitter.farge} />
}
}

klasse Barnebarn strekker seg til å Reagere.Komponent {
render(){
retur (
<div style={{color: dette.rekvisitter.farge}}>
Jepp, jeg er Barnebarnet
</div>
);
}
}

Hva om vi aldri ville Barnet komponent for å ha prop i første omgang? Sammenheng at vi slipper å gå gjennom Barnet komponent med farger og sende det direkte fra Foreldre til Barnebarnet:

klasse Foreldre strekker seg til å Reagere.Komponent {
// Tillate barn å bruke sammenheng
getChildContext() {
tilbake {
farge: ‘rød’
};
}

render(){
retur <Barnet />;
}
}

Forelder.childContextTypes = {
farge: PropTypes.string
};

klasse Barnet strekker seg til å Reagere.Komponent {
render() {
// Rekvisittar er fjernet og sammenheng flyter gjennom til Barnebarn
retur <Barnebarn />
}
}

klasse Barnebarn strekker seg til å Reagere.Komponent {
render() {
retur (
<div style={{color: dette.sammenheng.farge}}>
Jepp, jeg er fortsatt Barnebarnet
</div>
);
}
}

// Utsett farge til Barnebarnet
Barnebarn.contextTypes = {
farge: PropTypes.string
};

Mens litt mer detaljert, på oppsiden er å utsette farge hvor som helst ned i komponent-treet. Vel, noen ganger…

Det er Noen mest profesjonelle veldrevne

Du kan ikke alltid få kaken og spise den også, og sammenheng i sin nåværende form er ikke noe unntak. Det er noen underliggende problemer som du vil mer enn sannsynlig komme i kontakt med hvis du ender opp med å bruke kontekst for alle, men den enkleste tilfellene.

Kontekst er stor for å bli brukt på en innledende gjengi. Oppdatering av kontekst på fly? Ikke så mye. Et vanlig problem med sammenheng er at sammenhengen endringer er ikke alltid gjenspeiles i en komponent.

La oss dissekere disse mest profesjonelle veldrevne i mer detalj.

Gotcha 1: Ved Hjelp Av Ren Komponenter

Kontekst er vanskelig når du bruker PureComponent siden som standard er det ikke utføre noen grunne diffing som standard i en kontekst. Grunne diffing med PureComponent er testing for hvorvidt verdiene av objektet er strengt lik. Hvis de ikke er det, da (og bare da) vil komponenten oppdatering. Men siden sammenhengen ikke er avmerket, vel… det ikke skjer noe.

Se Penn Reagere Sammenheng Lys med PureComponents av Neal Fennimore (@nealfennimore) på CodePen.

Gotcha 2: Bør Komponent Oppdatering? Kanskje.

Sammenheng også oppdateres ikke hvis en komponent shouldComponentUpdate returnerer den false. Hvis du har en egendefinert shouldComponentUpdate metode, så vil du også trenger å ta konteksten i betraktning. For å aktivere oppdateringer i en kontekst, kan vi oppdatere hver enkelt komponent med en tilpasset shouldComponentUpdate som ser noe som dette.

import shallowEqual fra ‘fbjs/lib/shallowEqual’;

klasse ComponentThatNeedsColorContext strekker seg til å Reagere.PureComponent {
// nextContext vil vise farge så snart vi bruker ComponentThatNeedsColorContext.contextTypes
// MERK: for å Gjøre det nedenfor viser en konsoll feil kommer reagere v16.1.1
shouldComponentUpdate(nextProps, nextState, nextContext){
gå tilbake !shallowEqual(denne.rekvisitter, nextProps) || !shallowEqual(denne.staten, nextState) || !shallowEqual(denne.kontekst, nextContext);
}
}

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

Men dette løser ikke problemet til en mellommann PureComponent mellom foreldre og barn blokkere sammenheng oppdateringer. Dette betyr at hver PureComponent mellom foreldre og barn vil trenge for å ha contextTypes definert på det, og de ville også behovet for å ha en oppdatert shouldComponentUpdate metode. Og på dette punktet, det er mye arbeid for svært liten gevinst.

Bedre Tilnærminger til den mest profesjonelle veldrevne

Heldigvis har vi noen måter å omgå den mest profesjonelle veldrevne.

Tilnærming 1: Bruk en Høyere Orden Komponent

En Høyere Orden Komponent kan lese fra kontekst og passere nødvendig verdier videre til neste komponent som en prop.

import Reagere fra “reagerer’;

const withColor = (WrappedComponent) => {
klasse ColorHOC strekker seg til å Reagere.Komponent {
render() {
const { farge } = dette.kontekst;
retur <WrappedComponent style={{color: farge}} {…dette.rekvisitter} />
}
}

ColorHOC.contextTypes = {
farge: Reagerer.PropTypes.string
};

tilbake ColorHOC;
};

eksport const-Knappen = (props)=> < – knappen {…rekvisitter}> – Knappen</button>

// ColoredButton vil gjøre med hva farge er for tiden i sammenheng med en stil prop
eksport const ColoredButton = withColor( Knapp );

Se Penn Reagere Sammenheng med Lys HOC av Neal Fennimore (@nealfennimore) på CodePen.

Tilnærming 2: Bruk Gjengi Rekvisitter

Gjengi Rekvisitter tillate oss å bruke rekvisitter for å dele koden mellom to komponenter.

klasse App strekker seg til å Reagere.Komponent {
getChildContext() {
tilbake {
farge: ‘rød’
}
}

render() {
retur < – Knappen />
}
}

Appen.childContextTypes = {
farge: Reagerer.PropTypes.string
}

// Hook ‘Farge’ – i ‘App’ kontekst
klasse Color strekker seg til å Reagere.Komponent {
render() {
gå tilbake til denne.rekvisitter.render(denne.sammenheng.farge);
}
}

Farge.contextTypes = {
farge: Reagerer.PropTypes.string
}

klasse Knappen strekker seg til å Reagere.Komponent {
render() {
retur (
<- knappen type=”button”>
{/* Gå tilbake farget tekst i-Knapp */}
<Farge gjengi={ color => (
<Tekst color={farge} tekst=”Knappen Tekst” />
) } />
</button>
)
}
}

klasse Teksten strekker seg til å Reagere.Komponent {
render(){
retur (

{dette.rekvisitter.tekst}

)
}
}

Tekst.propTypes = {
tekst: Reagerer.PropTypes.string,
farge: Reagerer.PropTypes.string,
}</Color></button>
Tilnærming 3: Dependency Injection

En tredje måte kan vi omgå disse mest profesjonelle veldrevne er å bruke Avhengighet Injeksjon for å begrense sammenheng API og la komponenter for å abonnere som trengs.

Den Nye Prosjekter

Den nye måten å bruke sammenheng, som for tiden er planlagt for de neste mindre utslipp av Reagere (16.3), har fordeler av å være mer lesbar og lettere å skrive uten den “mest profesjonelle veldrevne” fra tidligere versjoner. Vi har nå en ny metode som kalles createContext, som definerer en ny kontekst og returnerer både Leverandør og Forbruker.

Leverandøren etablerer en sammenheng som alle sub-komponenter kan koble til. Det er hektet på via Forbruker som bruker en render prop. Det første argumentet til at gjengi prop funksjon, er den verdi som vi har gitt til Leverandøren. Ved å oppdatere verdien innenfor Leverandør, alle forbrukere vil bli oppdatert for å gjenspeile den nye verdien.

Som en annen fordel med å bruke den nye konteksten, har vi ikke lenger å bruke childContextTypes, getChildContext, og contextTypes.

const ColorContext = Reagere.createContext(‘farge’);
klasse ColorProvider strekker seg til å Reagere.Komponent {
render(){
retur (
<ColorContext.Leverandør verdi={‘rød’}>
{ dette.rekvisitter.barn }
</ColorContext.Leverandøren>
)
}
}

klasse Foreldre strekker seg til å Reagere.Komponent {
render(){
// Wrap ‘Barn’ med vår farge leverandør
retur (
<ColorProvider>
<Barnet />
</ColorProvider>
);
}
}

klasse Barnet strekker seg til å Reagere.Komponent {
render(){
retur <Barnebarn />
}
}

klasse Barnebarn strekker seg til å Reagere.Komponent {
render(){
// Bruker vår sammenheng og passere farge i stil-attributt
retur (
<ColorContext.Forbruker>
{/* ‘farge’ er verdien fra vår Leverandør */}
{
color => (
<div style={{color: farge}}>
Jepp, jeg er fortsatt Barnebarnet
</div>
)
}
</ColorContext.Forbruker>
);
}
}

Separat Sammenhenger

Siden vi har mer detaljert kontroll i hvordan vi utsettes sammenheng og hvilke komponenter som er lov til å bruke det, kan vi individuelt wrap komponenter med ulike sammenhenger, selv om de bor i samme komponent. Vi kan se dette i neste eksempel, der du bruker LightProvider to ganger, kan vi gi to komponenter, en egen kontekst.

Se Penn Reagere Sammenheng Lys med ny Kontekst av Neal Fennimore (@nealfennimore) på CodePen.

Konklusjon

Kontekst er et kraftig API, men det er også veldig lett å bruke på feil måte. Det er også noen regler for å bruke det, og det kan være svært vanskelig å finne ut av problemene når komponentene gå galt. Mens Høyere-For Komponenter og avhengighet injeksjon tilby alternativer for de fleste tilfeller, kontekst kan brukes med fordel i isolerte deler av koden din base.

Med neste sammenheng selv om vi ikke lenger trenger å bekymre deg den mest profesjonelle veldrevne vi hadde med den forrige versjonen. Det fjerner å måtte angi contextTypes på individuelle komponenter og åpner opp muligheten for å definere nye sammenhenger i et gjenbrukbart måte.