Flutter vs. Dart
De meeste mensen halen Flutter en Dart door elkaar alsof ze hetzelfde zijn, vooral omdat Dart en Flutter nauw samenwerken in crossplatformontwikkeling. Beide zijn essentieel voor het bouwen van android...
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:
gebruik;import { useState,useEffect } from "reageren";
exportstandaard functie FunctieComponent() {
const [value, setValue] = useState(1);
const [doubleValue, setDoubleValue] = useState(1);
als (waarde > 3) {
useEffect() => setDoubleValue(value * 2),[value]);
}
return (
{`Enkel ${waarde} Dubbel ${dubbelValue}`}
);
}
```
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 scheduler.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.
Onthoud dat eslint een krachtig hulpmiddel is, het helpt us vangen veel potentiële bugs en fouten op. Het uitschakelen van de waarschuwingen is gevaarlijk, controleer altijd of het negeren van de waarschuwing een crash van de app kan veroorzaken.
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:
const [value, setValue] = useState(0);
const [value, setValue] = useState() => {
console.log("INIT");
return 0;
});
Hoe kan ik controleren of de eerste manier echt wordt aangeroepen bij elke render? Maak een functie en geef deze door als initiële status:
const checkInit = () => {
console.log("INIT");
return 0;
};
const [value, setValue] = useState(checkInit());
```
En geef het nu door op de tweede manier:
const checkInit = () => {
console.log("INIT");
return 0;
};
const [value, setValue] = useState() => checkInit());
```
Gaaf, toch?

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
setValue((prevState) => prevState + 1);
// met objecten:
setUser((prevState) => ({ ...prevState, lastName: "Brzeczyszczykiewicz" });
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:
useEffect() => {
doSomething();
});
useEffect() => {
doSomething();
}, []);
useEffect() => {
doSomething(value);
}, [waarde]);
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.
useEffect() => {
console.log("neveneffect 1", count);
return () => {
console.log("BIJWERKING 1");
};
});
useEffect() => {
console.log("neveneffect 2", count);
return () => {
console.log("BIJWERKING 2");
};
}, []);
useEffect() => {
console.log("neveneffect 3", count);
return () => {
console.log("BIJWERKING 3");
};
}, [count]);
```
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?
useEffect() => {
// addEventListener
console.log("Toevoegen");
return () => {
// removeEventListener
console.log("Verwijderen");
};
}, [waarde]);
Je ontvangt dus eerst een verwijderen bericht, dan Voeg toe.
Er is één ding waar je op moet letten bij het gebruik van useEffect en asynchrone code daarbinnen. Kijk eens naar de onderstaande code:
useEffect() => {
fetch("https://picsum.photos/5000/5000").then() => {
setValue((prevState) => prevState + 1);
});
}, []);
In het begin ziet het er goed uit. Je haalt wat gegevensen wanneer de gegevens komen, de staat bijwerken. 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.
useEffect() => {
laat gemonteerd = true;
fetch("https://picsum.photos/5000/5000").then() => {
if (mounted) {
setValue((prevState) => prevState + 1);
}
});
return () => {
mounted = false;
};
}, []);
```
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.
Waar dient het voor? Gegevens delen zonder props door te geven. Bestaat uit de volgende elementen:
const user = {
naam: "Adam",
achternaam: "Kowalski",
};
export const UserContext = createContext(user);
;
```
In child moet je de context importeren en de useContext Hook aanroepen en die context als argument doorgeven.
importeer { UserContext } van "./App";
const {naam } = useContext(UserContext);
terugkeren <h1>Hallo {naam}<>
```
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.
Hiermee kunnen we de status beheren en opnieuw weergeven wanneer de status verandert - zoals bij useState. Het is vergelijkbaar met de redux reducer. Deze is beter dan useState als de toestandslogica gecompliceerder is.
const [status, dispatch] = useReducer(reducer, initialArg);
Er is ook een derde argument dat kan worden doorgegeven aan de useReducer - de init-functie.
const [status, dispatch] = useReducer(reducer, initialArg, init);
Waar dient het voor? Het kan worden gebruikt wanneer we de toestand willen resetten naar de beginwaarde. Hieronder vind je een mooi voorbeeld:
// Ouder
// Kind
functie init(initialNumber) {
return { number: initialNumber };
}
functie reducer(state, action) {
schakel (actie.type) {
geval "change":
return {getal: Math.random() };
geval "reset":
return init(action.payload);
standaard:
throw new Error();
}
}
export default functie ChildComponent({ getFactorial }) {
const [state, dispatch] = useReducer(reducer, initialNumber, init);
return (
<>
<h2>Nummer: {staat.nummer}</h2>
<button
onclick="{()" > dispatch({type: "reset", payload: initialNumber })}
>
Reset
</button>
<button onclick="{()" > verzenden({type: "wijzigen" })}>Tekenen</button>
</>
);
}

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
// Ouder
const getSquaredValue = () => count * count;
...
terugkeren (
)
Controleer dan in child component hoeveel keer het effect Hook zal worden aangeroepen na het toevoegen van die functie aan de afhankelijkheidsarray:
// Kind
useEffect() => {
console.log("getSquaredValue", getSquaredValue());
}, [getSquaredValue]);
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
const getSquaredValue = useCallback() => count * count, [count])
We kunnen ook enkele parameters doorgeven aan deze functie:
const getSquaredValue = useCallback(
(multiplicator) => count * count * multiplicator,
[graaf]
);
const memoizedValue = useMemo() => {
return doSomething(value);
}, [waarde]);
Je moet het alleen in 2 scenario's gebruiken:
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:
Probeer het eerst zonder useMemo:
const hobbit = {naam: "Bilbo" };
useEffect() => {
console.log("Hallo ", hobbit.naam);
}, [hobbit]);
```
Je krijgt ook een waarschuwing:
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
Probeer het dan met useMemo:
const hobbit = useMemo() => {
return {naam: "Bilbo" };
}, []);
useEffect() => {
console.log("Hallo ", hobbit.naam);
}, [hobbit]);
```
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:
exportstandaard functie OngecontroleerdForm() {
const input = useRef();
const handleSubmit = (e) => {
e.preventDefault();
console.log(input.current.value);
};
return (
);
}
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.
const [value, setValue] = useState("");
laat prevValue = useRef("");
useEffect() => {
prevValue.current = waarde;
}, [waarde]);
setValue(e.target.value)}>;
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 web toepassingen . 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 .
Einde van deel 1
Lees meer:
JavaScript is helemaal dood. Een kerel op het internet