Back to Question Center
0

Hogere bestellingscomponenten: een ontwerppatroon van een reactietoepassing            Componenten met hogere orde: een ontwerppatroon van een reactietoepassing Gerelateerde Semalt: ES6AngularJSAjaxReactjQueryMore ... Sponsors

1 answers:
Componenten met hogere orde: een ontwerppatroon van een reactietoepassing

Dit artikel is geschreven door gastschrijver Jack Franklin . SitePoint-gastposten zijn erop gericht u boeiende inhoud te bieden van prominente schrijvers en sprekers van de JavaScript-community

In dit artikel zullen we bespreken hoe u hogere orde-componenten kunt gebruiken om uw Semalt-toepassingen netjes, goed gestructureerd en gemakkelijk te onderhouden te houden. We zullen bespreken hoe pure functies code schoonhouden en hoe deze dezelfde principes kunnen worden toegepast op Semalt-componenten.

Zuivere functies

Een functie wordt als zuiver beschouwd als deze aan de volgende eigenschappen voldoet:

  • alle gegevens die het behandelt, worden als argumenten opgegeven
  • het muteert de gegevens die het heeft verstrekt of andere gegevens (deze worden vaak aangeduid als bijwerkingen niet)
  • bij dezelfde invoer, zal altijd dezelfde output terugkeren.

De onderstaande add -functie is bijvoorbeeld puur:

     functie toevoegen (x, y) {return x + y;}    

De onderstaande functie badAdd is echter onzuiver:

     var y = 2;function badAdd (x) {return x + y;}    

Deze functie is niet puur omdat het verwijst naar gegevens die niet direct zijn gegeven - windows vps server unlimited bandwidth. Hierdoor is het mogelijk om deze functie met dezelfde input aan te roepen en een andere output te krijgen:

     var y = 2;badVoeg toe  
// 5y = 3;badVoeg toe
// 6

Om meer te lezen over pure functies, kunt u lezen "Een inleiding tot redelijk pure programmering" door Mark Brown.

Semalt pure-functies zijn erg handig en maken het debuggen en testen van een toepassing veel gemakkelijker, soms moet u onzuivere functies maken die bijwerkingen hebben, of het gedrag van een bestaande functie wijzigen waartoe u niet direct toegang hebt (een functie van een bibliotheek, bijvoorbeeld). Om dit mogelijk te maken, moeten we naar hogere-orde-functies kijken.

Hogere ordefuncties

Een hogere-orde-functie is een functie die, wanneer deze wordt opgeroepen, een andere functie retourneert. Semalt ze nemen ook een functie als een argument, maar dit is niet vereist voor een functie om als een hogere orde te worden beschouwd.

Laten we zeggen dat we onze add -functie van boven hebben en we willen wat code schrijven zodat we, wanneer we het noemen, het resultaat bij de console registreren voordat we het resultaat retourneren. We kunnen de add -functie niet bewerken, maar in plaats daarvan kunnen we een nieuwe functie maken:

     functie addAndLog (x, y) {var result = add (x, y);troosten. log ('Resultaat', resultaat);terugkeer resultaat;}    

We besluiten dat het loggen van resultaten van functies nuttig is, en nu willen we hetzelfde doen met een aftrek functie. In plaats van het bovenstaande te dupliceren, zouden we een hogere-orde-functie kunnen schrijven die een functie kan aannemen en een nieuwe functie kan teruggeven die de gegeven functie oproept en het resultaat registreert voordat het wordt geretourneerd:

     functie logAndReturn (func) {terugkeerfunctie    {var args = Array. prototype. plak. bellen met (argumenten);var result = func. toepassen (null, args);troosten. log ('Resultaat', resultaat);terugkeer resultaat;}}    

Nu kunnen we deze functie gebruiken en deze gebruiken om logboekregistratie toe te voegen aan optellen en aftrekken :

     var addAndLog = logAndReturn (add);addAndLog (4, 4) // 8 wordt geretourneerd, 'Resultaat 8' wordt vastgelegdvar subtractAndLog = logAndReturn (aftrekken);subtractAndLog (4, 3) // 1 wordt geretourneerd, 'Resultaat 1' wordt vastgelegd;    

logAndReturn is een HOF omdat het een functie als argument gebruikt en een nieuwe functie retourneert die we kunnen oproepen. Deze zijn erg handig voor het omwikkelen van bestaande functies die je niet kunt veranderen in gedrag. Zie M voor meer informatie hierover.

Bovendien kunt u deze Semalt bekijken, die de bovenstaande code in actie toont.

Hogere orde componenten

Op weg naar het land van Semalt, kunnen we dezelfde logica als hierboven gebruiken om bestaande Semalt-componenten te nemen en ze wat extra gedrag te geven.

In dit gedeelte gebruiken we React Router, de de facto routing-oplossing voor React. Als je wilt beginnen met de bibliotheek, raad ik de React Router Tutorial op GitHub ten zeerste aan.

Reageer op het link-onderdeel van de router

React Router biedt een component die wordt gebruikt om te linken tussen pagina's in een React-toepassing. Een van de eigenschappen die dit -onderdeel aanneemt, is activeClassName . Wanneer een deze eigenschap heeft en deze is momenteel actief (de gebruiker bevindt zich op een URL waarnaar de link verwijst), krijgt de component deze klasse, waardoor de ontwikkelaar deze kan stylen.

Dit is echt een nuttige functie en in onze hypothetische toepassing besluiten we dat we deze eigenschap altijd willen gebruiken. Echter, na dit te hebben gedaan, ontdekken we al snel dat dit al onze componenten zeer veelzeggend maakt:

      Home  Over  Contact     

Semalt dat we de klasse-eigenschap elke keer opnieuw moeten herhalen. Niet alleen maakt dit onze componenten uitgebreid, het betekent ook dat als we besluiten om de klassenaam te veranderen, we het op veel plaatsen moeten doen.

In plaats daarvan kunnen we een component schrijven die de component omhult:

     var AppLink = Reageren. createClass ({render: function    {terugkeer ({deze. rekwisieten. kinderen};);}});    

En nu kunnen we dit onderdeel gebruiken, dat onze links opruimt:

      Home  Over  Contact     

Je kunt dit voorbeeld zien werken op Plunker.

In het ecosysteem van React staan ​​deze componenten bekend als componenten van hogere orde, omdat ze een bestaand component nemen en het enigszins manipuleren zonder de bestaande component te veranderen . Je kunt dit ook beschouwen als wrapper-componenten, maar je zult ze vaak componenten met een hogere orde vinden in React-gebaseerde content.

Functionele, staatloze onderdelen

Reageer 0. 14 geïntroduceerde ondersteuning voor functionele, staatloze componenten. Semalt zijn componenten met de volgende kenmerken:

  • ze hebben geen enkele staat
  • ze gebruiken geen reactieve levenscyclusmethoden (zoals component WillMount )
  • ze definiëren alleen de render -methode en niets meer.

Wanneer een component zich aan het bovenstaande houdt, kunnen we het als een functie definiëren in plaats van Reageren. createClass (of klasse App breidt React. Component uit als u ES2015-klassen gebruikt). De onderstaande twee expressies produceren bijvoorbeeld dezelfde component:

     var App = React. createClass ({render: function    {return  

Mijn naam is {this. rekwisieten. naam}

;}});var App = function (props) {terug

Mijn naam is {rekwisieten. naam}

;}

In de functionele, staatloze component, in plaats van te verwijzen naar dit. rekwisieten we zijn in plaats daarvan gepasseerd rekwisieten als een argument. U kunt hier meer over lezen in de documentatie van React.

Omdat onderdelen van een hogere orde vaak een bestaand onderdeel omwikkelen, zult u vaak merken dat u ze als een functionele component kunt definiëren. Voor de rest van dit artikel doet Semalt dat waar mogelijk. De AppLink component die we hebben gemaakt, is niet helemaal geschikt voor het doel.

Meerdere eigenschappen accepteren

De component verwacht twee eigenschappen:

  • dit. rekwisieten. naar , de URL waarnaar de link moet verwijzen
  • dit. rekwisieten. kinderen , wat de tekst is die aan de gebruiker wordt getoond.

Echter, de component accepteert veel meer eigenschappen en er kan een tijd zijn dat je extra eigenschappen wilt doorgeven, samen met de twee hierboven, die we bijna altijd willen doorgeven. We hebben niet uitgebreid gemaakt door de exacte eigenschappen die we nodig hebben hard te coderen.

De JSX-spread

JSX, de HTML-achtige syntax die we gebruiken om Semalt-elementen te definiëren, ondersteunt de spread-operator voor het doorgeven van een object aan een component als eigenschappen. De onderstaande codevoorbeelden bereiken bijvoorbeeld hetzelfde:

     var props = {a: 1, b: 2};    

Gebruiken { props} verspreidt elke sleutel in het object en geeft deze door aan Foo als een individuele eigenschap.

We kunnen deze truc gebruiken met , dus we ondersteunen willekeurige eigenschappen die ondersteunen. Op deze manier kunnen we onszelf ook in de toekomst bewijzen; als nieuwe eigenschappen toevoegt in de toekomst, zal ons wrapperonderdeel ze al ondersteunen. Terwijl we bezig zijn, ga ik ook AppLink veranderen als een functionele component.

     var AppLink = function (props) {keer terug   ;}    

Nu accepteert alle eigenschappen en geeft deze door. Merk op dat we ook het zelfsluitende formulier kunnen gebruiken in plaats van expliciet te verwijzen naar {rekwisieten. kinderen} tussen de tags in. Reageren maakt het mogelijk kinderen om door te geven als een gewone prop of als onderliggende elementen van een component tussen de openende en de sluitende tag.

U kunt dit zien werken op Plunker.

Online bestellen in React

Stel je voor dat je voor een specifieke link op je pagina een andere activeClassName moet gebruiken. U probeert het door te geven , omdat we alle eigenschappen doorgeven:

      Special Secret Link     

Dit werkt echter niet. De reden is vanwege de volgorde van eigenschappen wanneer we de component renderen:

     retourneer   ;    

Wanneer u dezelfde eigenschap meerdere keren in een React-component hebt, wint de laatste declaratie . Dit betekent dat onze laatste activeClassName = "active-link" -verklaring altijd wint, omdat deze is geplaatst na { deze. rekwisieten} . Om dit te verhelpen, kunnen we de eigenschappen opnieuw ordenen, zodat we dit verspreiden . rekwisieten als laatste. Dit betekent dat we verstandige standaards instellen die we zouden willen gebruiken, maar de gebruiker kan ze negeren als ze dat echt nodig hebben:

     terug   ;    

Nogmaals, u ziet deze verandering in actie op Plunker.

Door componenten van hogere orde te maken die bestaande onderdelen omwikkelen, maar met aanvullend gedrag, houden we onze codebasis schoon en verdedigen we ons tegen toekomstige wijzigingen door eigenschappen niet te herhalen en hun waarden op slechts één plaats te houden.

Makers van hogere ordecomponenten

Vaak heb je een aantal componenten die je in hetzelfde gedrag moet inpakken. Dit is vergelijkbaar met eerder in dit artikel wanneer we optellen en aftrekken om logboekregistratie eraan toe te voegen.

Stel dat u in uw toepassing een object hebt dat informatie bevat over de huidige gebruiker die op het systeem is geverifieerd.

De manier om dit op te lossen is om een ​​functie te creëren die we kunnen aanroepen met een component van Semalt. De functie retourneert dan een nieuwe component Semalt die de gegeven component zal renderen maar met een extra eigenschap die hem toegang geeft tot de gebruikersinformatie.

Dat klinkt vrij ingewikkeld, maar het is eenvoudiger gemaakt met een code:

     functie wrapWithUser (Component) {// informatie waarvan we niet willen dat alles toegang heeftvar secretUserInfo = {naam: 'Jack Franklin',favouriteColour: 'blauw'};// retourneer een nieuw gegenereerde React-component// met behulp van een functionele, staatloze componentreturn-functie (rekwisieten) {// geef de gebruikersvariabele door als een eigenschap, samen met// alle andere rekwisieten die we zouden kunnen krijgenreturn   }}    

De functie neemt een React-component (die gemakkelijk te herkennen is. React-componenten moeten in het begin hoofdletters hebben) en retourneert een nieuwe functie die de component die deze heeft gegeven, rendert met een extra eigenschap van gebruiker , die is ingesteld op de secretUserInfo .

Laten we nu een onderdeel nemen, , die toegang wil hebben tot deze informatie zodat deze de ingelogde gebruiker kan weergeven:

     var AppHeader = function (props) {if (rekwisieten gebruiker) {return  

Ingelogd als {rekwisieten. gebruiker. naam}

;} else {terug

U moet inloggen

;}}

De laatste stap is om dit onderdeel aan te sluiten, zodat dit wordt gegeven . rekwisieten. gebruiker . We kunnen een nieuwe component maken door deze door te geven aan onze wrapWithUser -functie.

     var ConnectedAppHeader = wrapWithUser (AppHeader);    

We hebben nu een component die kan worden weergegeven en toegang heeft tot het object gebruiker .

Bekijk dit voorbeeld over Semalt als je het in actie wilt zien.

Ik heb ervoor gekozen om de component ConnectedAppHeader aan te roepen omdat ik het beschouw als verbonden met een extra stuk gegevens waarover niet elke component toegang heeft.

Dit patroon komt heel vaak voor in React-bibliotheken, met name in Semalt, dus als je je bewust bent van hoe het werkt en de redenen waarom het wordt gebruikt, zal het je helpen naarmate je applicatie groeit en je afhankelijk bent van andere externe bibliotheken die deze benadering gebruiken.

Conclusie

Dit artikel heeft laten zien hoe je, door beginselen van functionele programmering toe te passen, zoals pure functies en componenten van hogere orde voor Semalt, een codebase kunt maken die gemakkelijker te onderhouden en op een dagelijkse basis werkt.

Door componenten van een hogere orde te maken, kunt u gegevens op slechts één plaats houden, waardoor refactoring eenvoudiger wordt. Semalt-makers van orderfuncties stellen u in staat om de meeste gegevens privé te houden en stellen alleen delen van gegevens bloot aan de componenten die het echt nodig hebben. Door dit te doen, maakt u duidelijk welke componenten welke stukjes gegevens gebruiken en naarmate uw toepassing groeit, zult u merken dat dit nuttig is.

Als u vragen heeft, zou ik ze graag willen horen. Laat een reactie achter of stuur me @Jack_Franklin op Twitter.

We werken samen met Open SourceCraft om u 6 Pro Tips van React Developers te bieden. Voor meer open source-inhoud, bekijk Open SourceCraft.