window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(funktion () { var w = vindue if (w.LeadBooster) { console.warn('LeadBooster findes allerede') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Et dybere kig på de mest populære React-kroge - The Codest
Codest
  • Om os
  • Serviceydelser
    • Udvikling af software
      • Frontend-udvikling
      • Backend-udvikling
    • Staff Augmentation
      • Frontend-udviklere
      • Backend-udviklere
      • Dataingeniører
      • Cloud-ingeniører
      • QA-ingeniører
      • Andet
    • Det rådgivende
      • Revision og rådgivning
  • Industrier
    • Fintech og bankvirksomhed
    • E-commerce
    • Adtech
    • Sundhedsteknologi
    • Produktion
    • Logistik
    • Biler
    • IOT
  • Værdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leder af levering
  • Vores team
  • Casestudier
  • Ved hvordan
    • Blog
    • Møder
    • Webinarer
    • Ressourcer
Karriere Tag kontakt til os
  • Om os
  • Serviceydelser
    • Udvikling af software
      • Frontend-udvikling
      • Backend-udvikling
    • Staff Augmentation
      • Frontend-udviklere
      • Backend-udviklere
      • Dataingeniører
      • Cloud-ingeniører
      • QA-ingeniører
      • Andet
    • Det rådgivende
      • Revision og rådgivning
  • Værdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leder af levering
  • Vores team
  • Casestudier
  • Ved hvordan
    • Blog
    • Møder
    • Webinarer
    • Ressourcer
Karriere Tag kontakt til os
Pil tilbage GÅ TILBAGE
2021-12-07
Udvikling af software

Et dybere kig på de mest populære React-kroge

Codest

Pawel Rybczynski

Software Engineer

I løbet af mange interviews har jeg bemærket, at selv erfarne programmører har problemer med at skelne mellem Hooks, for slet ikke at tale om deres mere avancerede muligheder. Derfor vil jeg i denne artikel forsøge at forklare, hvordan Hooks skal bruges.

De vigtigste ting, du skal huske om Hooks:

  • de kan kun bruges i funktionskomponenter - klassekomponenter har deres egen livscyklusimplementering;
  • De starter altid med brug;
  • Du kan bruge så mange Hooks, du vil, men du skal huske, at brugen af dem har indflydelse på den samlede ydelse;
  • de skal udføres i samme rækkefølge ved hver rendering ... men hvorfor? Lad os se på et eksempel:
import { useState,useEffect } fra "react";

export default function FunctionComponent() {
const [value, setValue] = useState(1);
const [doubleValue, setDoubleValue] = useState(1);
if (værdi > 3) {
  useEffect(() => setDoubleValue(value * 2),[value]);
}

return (
  <>
    <p>{`Enkelt ${værdi} Dobbelt ${doubleValue}`}</p>
    <button onclick="{()" > setValue(værdi + 1)}&gt;Check</button>
  </>
);
}
```

I første omgang får du en advarsel fra eslint:

<code>srcFunctionComponent.js
   Linje 11:5: React Krog "useEffect" kaldes betinget. <strong>React-kroge</strong> skal kaldes i nøjagtig samme rækkefølge i hver komponent render .eslintreact-hooks/rules-of-hooks

Som du kan se, er det kun en eslint-advarsel, så du kan deaktivere den ved at tilføje en kommando nedenunder i toppen af filen Funktionskomponent

/* eslint-disable react-hooks/rules-of-hooks */ 

og det vil virke, men kun indtil vi opfylder den betingelse, der kører vores Hook. Den næste ting, vi vil se, er denne fejl.

Fejl, der ikke blev opdaget: Renderede flere kroge end under den forrige rendering.
     React 5
     FunctionComponent FunctionComponent.js:11
     React 12
     unstable_runWithPriority scheduler.development.js:468
     React 17
     js index.js:7
     js main.chunk.js:905
     Webpack 7
 react-dom.development.js:15162

Hvorfor sker dette? React er afhængig af den rækkefølge, krogene kaldes i, da React ikke ville vide, hvad der skulle returneres for useEffect, fordi der ikke var en sådan krog i linjen at tjekke.

Husk, at eslint er et stærkt værktøj, der hjælper os med at finde mange potentielle bugs og fejl. Det er farligt at deaktivere dens advarsler, så tjek altid, om det kan få appen til at gå ned, hvis du ignorerer advarslen.

useState

Du ved sikkert, hvordan det ser ud 😉.

const [value, setValue] = useState(0);

Så du har 4 elementer: tilstand (reaktiv værdi), opdateringsfunktion (setter), faktisk hook (funktion) og valgfri startværdi. Hvorfor returnerer den et array? Fordi vi kan omstrukturere det, som vi vil.

Nu vil jeg fokusere på det sidste element - den oprindelige værdi. Der er to måder at videregive den oprindelige tilstand på:

  1. Med hardcoded værdi eller andet - som vil blive kaldt ved hver gengivelse
const [value, setValue] = useState(0);
  1. Med en funktionsversion. Det er virkelig nyttigt, hvis vi kun vil køre den indledende tilstand én gang, ved den allerførste gengivelse. Måske er du nødt til at foretage en masse komplekse beregninger for at modtage den oprindelige tilstand? Det vil pænt reducere ressourceomkostningerne, yay!
const [value, setValue] = useState(() => {
   console.log("INIT");
   return 0;
 });

Hvordan kontrollerer jeg, at den første måde virkelig kaldes ved hver gengivelse? Opret en funktion, og send den som en indledende tilstand:

const checkInit = () => {
console.log("INIT");
return 0;
};

const [value, setValue] = useState(checkInit());
```

Og send den nu videre på den anden måde:

const checkInit = () => {
console.log("INIT");
return 0;
};

const [value, setValue] = useState(() => checkInit());
```

Sejt, ikke?

støj.png

En anden ting, der kan skabe fejl i app-flowet: Du ved sikkert, hvordan man opdaterer en tilstand, ikke?

setValue(1);

Ja ... men hvad nu, hvis jeg vil opdatere tilstanden ud fra en tidligere tilstand?

setValue(værdi + 1);

Ja... Men nej... Hvad nu, hvis du prøver at kalde setter-funktionen to gange, den ene efter den anden? Den anbefalede måde at opdatere en tilstand på, baseret på den tidligere tilstand, er at bruge en funktion. Det garanterer, at du henviser til den tidligere tilstand

setValue((prevState) => prevState + 1);
// med objekter:
setUser((prevState) => ({ ...prevState, efternavn: "Brzeczyszczykiewicz" }));

brugEffekt

Denne krog tager 2 argumenter (det andet er valgfrit), og vi bruger den til at håndtere bivirkninger. Og afhængigt af, hvad vi sender som det andet argument, vil krogen blive kaldt forskelligt:

  1. uden andet argument - hver gengivelse
useEffect(() => {
   gørnoget();
 });
  1. tomt array - kun ved første gengivelse
useEffect(() => {
   gørnoget();
 }, []);
  1. array med afhængigheder - hver gang værdien i afhængighedsarrayet ændres
useEffect(() => {
   doSomething(værdi);
 }, [værdi]);

Oprydning

Med useEffect kan vi bruge noget, der kaldes cleanup. Hvad kan man bruge det til? Det er meget nyttigt, men jeg synes, det er bedst til at rense event-lyttere. Lad os sige, at du vil oprette en event-lytter, som afhænger af en eller anden tilstand. Du ønsker ikke at tilføje en ny event-lytter ved hver tilstandsændring, for efter nogle få renderinger vil der være så mange lyttere, at det vil påvirke appens ydeevne. En god måde at undgå sådanne ting på er at bruge oprydningsfunktionen. Hvordan gør man det? Du skal bare tilføje en returfunktion til useEffect.

useEffect(() => {
console.log("bivirkning 1", count);
return () => {
console.log("DESTROYED 1");
};
});

useEffect(() => {
console.log("bivirkning 2", count);
return () => {
console.log("DESTROYED 2");
};
}, []);

useEffect(() => {
console.log("bivirkning 3", count);
return () => {
console.log("DESTROYED 3");
};
}, [count]);
```

Fordi det er inde i useEffect Hook, kaldes return afhængigt af dependency array - ved hver rendering, kun ved den første rendering, eller når værdien i dependency array ændres. Men når komponenten afmonteres, vil cleaning blive kaldt på det andet argument uanset hvad. Returneringen Kode kaldes før den egentlige kode fra Hook. Det er meget logisk - først renser du den gamle, så opretter du en ny. Er det ikke rigtigt?

useEffect(() => {
   // addEventListener
   console.log("Tilføj");
   return () => {
     // fjernEventListener
     console.log("Fjern");
   };
 }, [value]);

Så først vil du modtage en fjerne besked, så Tilføj.

Der er én ting, man skal være opmærksom på, når man bruger useEffect og asynkron kode indeni. Se på koden nedenfor:

useEffect(() => {
   fetch("https://picsum.photos/5000/5000").then(() => {
     setValue((prevState) => prevState + 1);
   });
 }, []);

Til at begynde med ser det ok ud. Du henter nogle data, og når dataene kommer, opdaterer du tilstanden. Og her er fælden:

Nogle gange vil du modtage en sådan advarsel:
Kan ikke udføre en React-tilstandsopdatering på en afmonteret komponent. Dette er en no-op, men det indikerer en hukommelseslækage i din applikation. Det kan løses ved at annullere alle abonnementer og asynkrone opgaver i en useEffect-oprydningsfunktion.

Årsagen er, at komponenten kan afmonteres i mellemtiden, men appen vil stadig forsøge at opdatere komponentens tilstand, efter at løftet er opfyldt. Hvordan håndterer man det? Du skal tjekke, om komponenten findes.

useEffect(() => {
let mounted = true;
fetch("https://picsum.photos/5000/5000").then(() => {
if (mounted) {
setValue((prevState) => prevState + 1);
}
});

return () => {
monteret = falsk;
};
}, []);
```

Bemærk: Der findes en meget lignende krog => useLayoutEffect() - tilbagekaldet kører efter rendering af komponenten, men før dom'en opdateres visuelt. Det er nyttigt, når du arbejder med getBoundingClientRect(), men du bør bruge useEffect som standard. Hvorfor det? Fordi det kan blokere visuelle opdateringer - når du har en kompleks kode inde i din effekt Hook.

brugKontekst

Hvad kan man bruge det til? Deling af data uden at sende props. Består af følgende elementer:

  1. Skabt kontekst - data
  2. Kontekstudbyder - giver kontekst til alle børn
  3. Overført værdi - data, du vil dele
  4. Krog - til at læse delte data
const bruger = {
navn: "Adam",
efternavn: "Kowalski",
};

export const UserContext = createContext(user);

;
```

I child skal du importere konteksten og kalde useContext Hook og sende konteksten som et argument.

import { UserContext } fra "./App";

const { navn } = useContext(UserContext);

return <h1>Hej {navn}<>
```

Voilà. Det ser fedt ud. Mest til overførsel af globale data som temaer osv. Anbefales ikke til brug i opgaver med meget dynamiske ændringer.

Vi kan selvfølgelig oprette en brugerdefineret kontekstudbyder og en brugerdefineret krog for at reducere boilerplate i stedet ... men jeg vil beskæftige mig med brugerdefinerede kroge i den næste artikel.

useReducer

Den giver os mulighed for at styre tilstanden og gengive den, når den ændres - ligesom useState. Det svarer til redux reducer. Denne er bedre end useState, når tilstandslogikken er mere kompliceret.

const [state, dispatch] = useReducer(reducer, initialArg); 
  • Returnerer den aktuelle tilstand med en afsendelsesmetode.
  • Til forskel fra redux specificeres den oprindelige værdi, når krogen kaldes.

Der er også et tredje argument, som kan sendes til useReducer - init-funktionen.

const [state, dispatch] = useReducer(reducer, initialArg, init);

Hvad kan man bruge den til? Den kan bruges, når vi vil nulstille tilstanden til dens oprindelige værdi. Nedenfor kan du se et godt eksempel:

// Forælder

// Barn
funktion init(initialNumber) {
return { number: initialNumber };
}

function reducer(state, action) {
switch (action.type) {
tilfælde "change":
return { number: Math.random() };
case "reset":
return init(action.payload);
standard:
throw new Error();
}
}

export default function ChildComponent({ getFactorial }) {
const [state, dispatch] = useReducer(reducer, initialNumber, init);

return (
<>
   <h2>Nummer: {state.number}</h2>
      <button
        onclick="{()" > dispatch({ type: "reset", payload: initialNumber })}.
      &gt;
        Nulstil
      </button>
      <button onclick="{()" > dispatch({ type: "change" })}&gt;Tegne</button>
    </>
  );
}

Nummer: {state.number}

ReducerInit.png

useCallback

Hvornår skal man bruge det? Når vi ønsker at opnå referentiel lighed (og dermed reducere antallet af oprettede funktioner). Denne krog returnerer funktionen, i modsætning til useMemo, som returnerer værdien.

Eksempel: Opret en funktion i den overordnede komponent, og send den derefter via props

// Parent
 const getSquaredValue = () => count * count;
 ...
 return (
   
 )

Tjek derefter i den underordnede komponent, hvor mange gange effekten Hook vil blive kaldt efter tilføjelse af funktionen til afhængighedsarrayet:

// Barn
 useEffect(() => {
   console.log("getSquaredValue", getSquaredValue());
 }, [getSquaredValue]);

Den vil logge på konsollen ved hver gengivelse! Selv hvis værdierne inde i getSquaredValue() funktion blev ikke ændret. Men vi kan undgå dette ved at pakke funktionen ind i useCallback

const getSquaredValue = useCallback(() => count * count, [count])

Vi kan også sende nogle parametre til denne funktion:

const getSquaredValue = useCallback(
   (multiplikator) => tæller * tæller * multiplikator,
   [count]
 );

brugMemo

const memoizedValue = useMemo(() => {
   return doSomething(value);
 }, [værdi]);
  • Det er ikke neutralt, når man ser på ressourceomkostningerne - useMemo skal kaldes ved hver gengivelse, den gemmer værdien i hukommelsen og sammenligner (hukommelsesoverhead),
  • bruger Memoization - optimeringsteknikken, en specifik form for caching.

Du bør kun bruge den i to scenarier:

  1. Hvis du vil undgå at kalde en kompleks kode ved hver gengivelse;
  2. Hvis du vil opnå referencemæssig lighed.

Lad os se lidt nærmere på det andet tilfælde. Vi vil bruge useEffect med et objekt som en afhængighed. Da objekter sammenlignes ved hjælp af deres reference, vil useEffect blive kaldt ved hver gengivelse. For at undgå den slags kan vi kombinere useEffect med useMemo for at memorere sådanne objekter og derefter sende de memorerede objekter til dependency-arrayet. Et kort eksempel:

Prøv først at gøre det uden useMemo:

const hobbit = { navn: "Bilbo" };

useEffect(() => {
console.log("Hello ", hobbit.name);
}, [hobbit]);
```

Du vil også modtage en advarsel:

Objektet 'hobbit' får afhængighederne af useEffect-krogen (linje 49) til at ændre sig ved hver rendering. Flyt det ind i useEffect-tilbagekaldet. Alternativt kan du pakke initialiseringen af 'hobbit' ind i sin egen useMemo ()-krog.eslintreact-hooks/exhaustive-deps

Så prøv med useMemo:

const hobbit = useMemo(() => {
return { name: "Bilbo" };
}, []);

useEffect(() => {
console.log("Hello ", hobbit.name);
}, [hobbit]);
```

useRef

Den vigtigste ting: useRef udløser ikke genrendering (som useState), fordi den ikke er forbundet med renderingscyklussen - den beholder den samme reference mellem renderinger.

const ref = useRef(0);

For at kalde den gemte værdi skal du bruge en aktuel egenskab (ref er et objekt) -. ref.nuværende

Det andet tilfælde, hvor vi kan bruge denne krog, er til at henvise til elementer i HTML. Hvert element har en ref-attribut. Så vi kan håndtere fokus, begivenheder osv.

Det tredje tilfælde er, at vi kan bruge refs til at håndtere ukontrollerede komponenter. Du kan læse mere om dem i react-dokumenter,
Men kort fortalt ser det sådan her ud:

export default function UncontrolledForm() {
  const input = useRef();

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(input.current.value);
  };

  return (
    
      
      Send.
    
  );
}

Som du kan se, er der ingen eventhandler, den husker bare den indtastede værdi. Det er godt til at håndtere grundlæggende formularer, hvor du bare vil læse gemte værdier, når du har brug for dem (f.eks. ved indsendelse).

Bonus: Det er fantastisk, når du har brug for at huske tidligere tilstandsværdier. Du kan bruge useEffect-krogen til det, bare send tilstanden til ref.

const [value, setValue] = useState("");

let prevValue = useRef("");

useEffect(() => {
  prevValue.current = værdi;
}, [værdi]);

 setValue(e.target.value)}>;

Som du kan se, er Hooks ikke så indlysende. Vi kan kombinere dem til at løse mange problemer. Du vil helt sikkert få stor gavn af at studere dette emne.

Og der er også brugerdefinerede kroge ...

Afslutningsvis, React-kroge har revolutioneret den måde React-udviklere tilgang til bygning webapplikationer . Ved at give en mere intuitiv og effektiv måde at styre tilstand og livscyklus på i funktionelle komponenter er hooks blevet en integreret del af React udvikling .

Uanset om du er en erfaren udvikler eller lige er startet med React, er det afgørende at forstå de mest populære hooks og deres anvendelsesmuligheder. Med hooks som useState, useEffect, useContext m.fl, React-komponenter kan bygges med renere og mere genanvendelig kode. Desuden er muligheden for at skabe Tilpassede kroge gør det muligt for udviklere at indkapsle og dele logik på tværs af flere komponenter, hvilket fremmer genanvendelighed og modularitet i koden. Efterhånden som React fortsætter med at udvikle sig og introducere nye funktioner, vil hooks utvivlsomt spille en central rolle i udnyttelsen af rammens fulde potentiale.

Så uanset om du arbejder på en lille funktionsapplikation eller en storstilet webapplikation, er det vigtigt at omfavne React-kroge vil forbedre dit udviklingsworkflow og åbne op for et væld af muligheder for at skabe robuste og funktionsrige React-applikationer .

Slut på del 1

Læs mere om det:

JavaScript er fuldstændig død. En fyr på internettet

Implementer GraphQL/MongoDB API ved hjælp af Netlify-funktioner

Sådan dræber du et projekt med dårlig kodningspraksis

Relaterede artikler

Udvikling af software

Byg fremtidssikrede webapps: Indsigt fra The Codest's ekspertteam

Oplev, hvordan The Codest udmærker sig ved at skabe skalerbare, interaktive webapplikationer med banebrydende teknologier, der leverer sømløse brugeroplevelser på tværs af alle platforme. Lær, hvordan vores ekspertise driver digital transformation og...

DENKODEST
Udvikling af software

Top 10 Letlands-baserede softwareudviklingsvirksomheder

Læs om Letlands bedste softwareudviklingsvirksomheder og deres innovative løsninger i vores seneste artikel. Find ud af, hvordan disse teknologiledere kan hjælpe med at løfte din virksomhed.

thecodest
Løsninger til virksomheder og scaleups

Grundlæggende om Java-softwareudvikling: En guide til succesfuld outsourcing

Udforsk denne vigtige guide til vellykket outsourcing af Java-softwareudvikling for at forbedre effektiviteten, få adgang til ekspertise og skabe projektsucces med The Codest.

thecodest
Udvikling af software

Den ultimative guide til outsourcing i Polen

Den voldsomme stigning i outsourcing i Polen er drevet af økonomiske, uddannelsesmæssige og teknologiske fremskridt, der fremmer it-vækst og et erhvervsvenligt klima.

TheCodest
Løsninger til virksomheder og scaleups

Den komplette guide til IT-revisionsværktøjer og -teknikker

IT-revisioner sikrer sikre, effektive og kompatible systemer. Lær mere om deres betydning ved at læse hele artiklen.

Codest
Jakub Jakubowicz CTO og medstifter

Tilmeld dig vores vidensbase, og hold dig opdateret om ekspertisen fra it-sektoren.

    Om os

    The Codest - International softwareudviklingsvirksomhed med tech-hubs i Polen.

    Storbritannien - Hovedkvarter

    • Kontor 303B, 182-184 High Street North E6 2JA
      London, England

    Polen - Lokale teknologiske knudepunkter

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Hjerneambassaden, Konstruktorska
      11, 02-673 Warszawa, Polen

      Codest

    • Hjem
    • Om os
    • Serviceydelser
    • Casestudier
    • Ved hvordan
    • Karriere
    • Ordbog

      Serviceydelser

    • Det rådgivende
    • Udvikling af software
    • Backend-udvikling
    • Frontend-udvikling
    • Staff Augmentation
    • Backend-udviklere
    • Cloud-ingeniører
    • Dataingeniører
    • Andet
    • QA-ingeniører

      Ressourcer

    • Fakta og myter om at samarbejde med en ekstern softwareudviklingspartner
    • Fra USA til Europa: Hvorfor beslutter amerikanske startups sig for at flytte til Europa?
    • Sammenligning af Tech Offshore-udviklingsknudepunkter: Tech Offshore Europa (Polen), ASEAN (Filippinerne), Eurasien (Tyrkiet)
    • Hvad er de største udfordringer for CTO'er og CIO'er?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Vilkår for brug af hjemmesiden

    Copyright © 2025 af The Codest. Alle rettigheder forbeholdes.

    da_DKDanish
    en_USEnglish de_DEGerman sv_SESwedish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek da_DKDanish