Tijdens veel interviews heb ik gemerkt dat zelfs ervaren programmeurs moeite hebben met het onderscheiden van Hooks, om nog maar te zwijgen over de meer geavanceerde mogelijkheden. Daarom zal ik in dit artikel proberen uit te leggen hoe Hooks moeten worden gebruikt.
De belangrijkste dingen die je moet onthouden over Haken:
ze kunnen alleen worden gebruikt in functiecomponenten - klassecomponenten hebben een eigen levenscyclusimplementatie;
ze beginnen altijd met gebruik;
je kunt zoveel haken gebruiken als je wilt, maar je moet onthouden dat het gebruik ervan invloed heeft op de algehele prestaties;
ze moeten bij elke render in dezelfde volgorde worden uitgevoerd... maar waarom? Laten we eens kijken naar een voorbeeld:
In het begin krijg je een waarschuwing van eslint:
<code>srcFunctieComponent.js
Regel 11:5: React Haak "useEffect" wordt voorwaardelijk aangeroepen. <strong>React Haken</strong> moet in exact dezelfde volgorde worden aangeroepen in elk component render .eslintreact-hooks/rules-of-hooks
Zoals je kunt zien, is het slechts een eslint-waarschuwing, dus je kunt het uitschakelen door een commando van onderen toe te voegen bovenaan de FunctieComponent
/* eslint-disable react-hooks/rules-of-hooks */
en het zal werken, maar alleen totdat we voldoen aan de voorwaarde die onze Hook uitvoert. Het volgende dat we zullen zien is deze fout.
Onopgeloste fout: Meer haken gerenderd dan tijdens de vorige render.
React 5
FunctieComponent FunctieComponent.js:11
React 12
onstabiel_runmetprioriteit planner.development.js:468
React 17
js index.js:7
js main.chunk.js:905
Webpack 7
react-dom.development.js:15162
Waarom gebeurt dit? React vertrouwt op de volgorde waarin de hooks worden aangeroepen, omdat React niet zou weten wat er moet worden teruggegeven voor het useEffect omdat er geen hook in de regel staat om te controleren.
Vergeet niet dat eslint een krachtig hulpmiddel is, het helpt ons veel potentiële bugs en fouten op te sporen. Het uitschakelen van de waarschuwingen is gevaarlijk, controleer altijd of het negeren van de waarschuwing een appcrash kan veroorzaken.
useState
Je weet vast wel hoe het eruitziet 😉
const [value, setValue] = useState(0);
Je hebt dus 4 elementen: state (reactieve waarde), update functie (setter), actuele hook (functie) en optionele initiële waarde. Waarom retourneert het een array? Omdat we het kunnen herstructureren zoals we willen.
Nu wil ik me richten op het laatste element - de initiële waarde. Er zijn twee manieren om de initiële status door te geven:
Door een vastgecodeerde waarde of iets dergelijks - die bij elke render wordt aangeroepen
const [value, setValue] = useState(0);
Door een functieversie. Het is echt handig als we de begintoestand maar één keer willen uitvoeren, bij de allereerste render. Misschien moet je veel complexe berekeningen maken om de begintoestand te ontvangen? Dit verlaagt de resourcekosten, joepie!
Nog iets dat bugs kan veroorzaken in de app flow: je weet waarschijnlijk wel hoe je een status moet bijwerken, toch?
setValue(1);
Juist... maar wat als ik de status wil bijwerken op basis van een vorige status?
setValue(waarde + 1);
Ja... Maar nee... Wat als je de setterfunctie twee keer achter elkaar probeert aan te roepen? De aanbevolen manier om een toestand bij te werken op basis van de vorige toestand is om een functie te gebruiken. Het garandeert dat je verwijst naar de vorige status
Deze haak neemt 2 argumenten (het tweede is optioneel) en we gebruiken het om neveneffecten af te handelen. En afhankelijk van wat we als tweede argument doorgeven, wordt de haak anders aangeroepen:
zonder tweede argument - elke render
useEffect() => {
doSomething();
});
lege array - alleen bij de eerste weergave
useEffect() => {
doSomething();
}, []);
array met afhankelijkheden - elke keer dat de waarde in de afhankelijkhedenarray verandert
Met useEffect kunnen we iets gebruiken dat opruimen wordt genoemd. Waar dient het voor? Het is erg handig, maar ik denk dat het het beste is voor het opschonen van event listeners. Laten we zeggen dat je een event listener wilt maken die afhankelijk is van een bepaalde toestand. Je wilt niet bij elke toestandsverandering een nieuwe event listener toevoegen, want na een paar renders zullen er zoveel listeners zijn dat het de prestaties van de app zal beïnvloeden. Een geweldige manier om zulke dingen te vermijden is door de opruimfunctie te gebruiken. Hoe doe je dat? Voeg gewoon een terugkeerfunctie toe aan het useEffect.
Omdat het in de useEffect Hook zit, wordt de return aangeroepen afhankelijk van de afhankelijkheidsarray - bij elke render, alleen bij de eerste render of wanneer de waarde in de afhankelijkheidsarray verandert. Maar wanneer de component wordt losgekoppeld, wordt cleaning hoe dan ook aangeroepen op het tweede argument. De terugkeer code wordt aangeroepen vóór de eigenlijke code van Hook. Het is heel logisch - eerst de oude opruimen, dan een nieuwe maken. Toch?
In het begin ziet het er goed uit. Je haalt wat gegevens op en wanneer de gegevens komen, werk je de status bij. En hier is de valkuil:
Soms krijg je zo'n waarschuwing: Kan geen React statusupdate uitvoeren op een niet-gemount component. Dit is een no-op, maar het wijst op een geheugenlek in uw toepassing. Om dit op te lossen, annuleert u alle abonnementen en asynchrone taken in een useEffect-opschoonfunctie.
De reden hiervoor is dat het component in de tussentijd kan worden ontkoppeld, maar de app zal nog steeds proberen de status van dat component bij te werken nadat de belofte is nagekomen. Hoe ga je hiermee om? Je moet controleren of de component bestaat.
Opmerking: er is een Hook die erg lijkt op useLayoutEffect() - de callback wordt uitgevoerd na het renderen van de component, maar voordat de dom visueel wordt bijgewerkt. Het is nuttig wanneer je werkt met getBoundingClientRect(), maar je zou standaard useEffect moeten gebruiken. Waarom? Omdat het visuele updates kan blokkeren - wanneer je een complexe code in je effect Hook hebt.
useContext
Waar dient het voor? Gegevens delen zonder props door te geven. Bestaat uit de volgende elementen:
Gecreëerde context - gegevens
Contextverschaffer - context verschaffen aan alle kinderen
Voilà. Ziet er cool uit. Meestal voor het doorgeven van globale gegevens zoals thema's, enz. Niet aanbevolen voor gebruik in taken met zeer dynamische veranderingen.
Natuurlijk kunnen we in plaats daarvan een aangepaste context provider en een aangepaste Hook maken om de boilerplate te verminderen... maar ik zal de aangepaste Hooks in het volgende artikel behandelen.
useReducer
Hiermee kunnen we de staat beheren en opnieuw weergeven wanneer de staat verandert - zoals bij useState. Het is vergelijkbaar met redux reducer. Deze is beter dan useState als de toestandslogica gecompliceerder is.
Wanneer gebruiken we het? Wanneer we referentiële gelijkheid willen bereiken (waardoor het aantal aangemaakte functies wordt verminderd). Deze Haak retourneert de functie, in tegenstelling tot useMemo die de waarde retourneert.
Voorbeeld: Maak een functie in het bovenliggende component en geef deze door via props
Het logt bij elke render naar de console! Zelfs als de waarden in de getSquaredValue() functie niet veranderd. Maar we kunnen dit vermijden door die functie in useCallback te wikkelen
Het is niet neutraal als je kijkt naar de kosten van bronnen - useMemo moet bij elke render worden aangeroepen, slaat de waarde op in het geheugen en vergelijkt (geheugenoverhead),
gebruikt Memoization - de optimalisatietechniek, een specifieke vorm van caching.
Je moet het alleen in 2 scenario's gebruiken:
Als u wilt voorkomen dat bij elke render een complexe code wordt aangeroepen;
Als je referentiële gelijkheid wilt bereiken.
Laten we het tweede geval wat nader bekijken. We willen useEffect gebruiken met een object als afhankelijkheid. Omdat objecten worden vergeleken door hun referentie, zal useEffect bij elke render worden aangeroepen. Om dit te voorkomen, kunnen we useEffect combineren met useMemo om dergelijke objecten te memoïseren en vervolgens die gememoiseerde objecten door te geven aan de afhankelijkheidsarray. Kort voorbeeld:
Het 'hobbit'-object zorgt ervoor dat de afhankelijkheden van de useEffect Hook (regel 49) bij elke render veranderen. Verplaats het binnen de useEffect callback. Als alternatief, wikkel de initialisatie van 'hobbit' in zijn eigen useMemo () haak.eslintreact-hooks/exhaustive-deps
Het belangrijkste: useRef triggert niet opnieuw renderen (zoals useState) omdat het niet verbonden is met de rendercyclus - het behoudt dezelfde referentie tussen renders.
const ref = useRef(0);
Om de opgeslagen waarde op te roepen, moet je een huidige eigenschap gebruiken (ref is een object) -. ref.stroom
Het tweede geval waarvoor we die haak kunnen gebruiken is om te verwijzen naar elementen in HTML. Elk element heeft een ref attribuut. Zo kunnen we focus, gebeurtenissen enz. afhandelen.
Het derde geval is dat we refs kunnen gebruiken om ongecontroleerde componenten te behandelen. Je kunt er meer over lezen in react-documenten, maar in het kort ziet het er zo uit:
Zoals je kunt zien is er geen event handler, het onthoudt gewoon de getypte waarde. Het is geweldig voor het afhandelen van eenvoudige formulieren wanneer je alleen opgeslagen waarden wilt lezen wanneer je ze nodig hebt (zoals bij het indienen).
Bonus: Het is geweldig als je vorige toestandswaarden moet onthouden. Je kunt hiervoor de useEffect Hook gebruiken, geef gewoon de toestand door aan de ref.
Zoals je kunt zien, zijn Hooks niet zo voor de hand liggend. We kunnen ze combineren om veel problemen op te lossen. Je zult zeker veel baat hebben bij het bestuderen van dit onderwerp.
En er zijn ook aangepaste haken...
Concluderend, React haken hebben een revolutie teweeggebracht in de manier waarop React ontwikkelaars benadering gebouw webtoepassingen . Door een intuïtievere en efficiëntere manier te bieden om de status en levenscyclus in functionele componenten te beheren, zijn hooks een integraal onderdeel geworden van React ontwikkeling .
Of je nu een doorgewinterde ontwikkelaar bent of net begint met React, het begrijpen van de populairste hooks en hun use cases is cruciaal. Met haken zoals useState, useEffect, useContext en meer, React onderdelen kan worden gebouwd met schonere en meer herbruikbare code. Bovendien is de mogelijkheid om aangepaste haken stelt ontwikkelaars in staat om logica in te kapselen en te delen over meerdere componenten, wat herbruikbaarheid en modulariteit van code bevordert. Terwijl React zich blijft ontwikkelen en nieuwe functies introduceert, zullen hooks ongetwijfeld een centrale rol spelen in het benutten van het volledige potentieel van het framework.
Dus of je nu werkt aan een kleine functie-app of een grootschalige webapplicatie, het omarmen van React haken zal je ontwikkelworkflow verbeteren en een overvloed aan mogelijkheden ontsluiten voor het maken van robuuste en functierijke React toepassingen .