Kako pravilno koristiti React Hookove useEffect i useState

Zadnje ažuriranje: 28/01/2026
Autor: Isaac
  • useState i useEffect koncentriraju većinu stanja i nuspojava Reactovih funkcionalnih komponenti, zamjenjujući mnoge klasične metode životnog ciklusa.
  • Učinak može uključivati ​​logiku čišćenja koja vraća funkciju, omogućujući vam upravljanje pretplatama, intervalima i drugim vanjskim resursima bez curenja memorije.
  • Niz ovisnosti kontrolira kada se svaki efekt izvršava i mora sadržavati sve reaktivne vrijednosti koje se u njemu koriste, balansirajući ispravnost i performanse.
  • Razdvajanje logike na nekoliko malih useEffects po odgovornosti poboljšava čitljivost, olakšava ponovnu upotrebu i smanjuje uobičajene pogreške poput beskonačnih renderiranja ili netočnih ovisnosti.

React useState i useEffect hookovi

Ako svakodnevno radite s Reactom, savladavanje useState i useEffect nije opcionalno.To je praktički svakodnevna stvar. Ova dva Hooka obrađuju većinu logike stanja i nuspojava bilo koje moderne aplikacije, od jednostavnog brojača do složenih sučelja s HTTP zahtjevima, pretplatama na događaje i animacijama.

Problem je što ih je vrlo lako koristiti "na oku" i završiti s curenjem memorije, beskonačnim renderiranjem ili efektima koji se pokreću kada ne bi trebali.U ovom ćemo članku smireno objasniti kako pravilno koristiti useState i, prije svega, useEffect: što točno radi, kako se odnosi na životni ciklus komponente, kako upravljati čišćenjem, kako optimizirati performanse pomoću niza ovisnosti i kako primijeniti napredne obrasce bez mučenja mozga.

Što su Hookovi i zašto su useState i useEffect toliko važni?

Hookovi su se pojavili u Reactu 16.8 kako bi omogućili korištenje stanja i drugih mogućnosti bez potrebe za klasama.Umjesto da se proteže od React.Component i baveći se metodama životnog ciklusa, radimo s funkcijama koje pozivaju Hookove poput useState y useEffect iznutra.

useState je Hook koji vam daje lokalno stanje unutar funkcionalne komponente.Vraća vrijednost i funkciju za njezino ažuriranje, i svaki put kada ažurirate to stanje, pokrećete novo renderiranje komponente. To je temelj za dinamičko sučelje: brojači, obrasci, zastavice učitavanja itd.

S druge strane, useEffect je Hook koji vam omogućuje izvršavanje sekundarnih efekata nakon renderiranja.To uključuje stvari poput zahtjeva za podacima, websocket pretplata, DOM slušača, timera, integracije s vanjskim bibliotekama ili ručnih DOM ažuriranja kada nema druge mogućnosti.

Ako dolazite iz komponenti klase, useEffect možete vidjeti kao kombinaciju componentDidMount, componentDidUpdate i componentWillUnmountali zapakirano u jednom deklarativnom API-ju. Ideja je razmišljati u smislu "efekta koji se javljaju nakon renderiranja", a ne odvojenih faza "sastavljanja" ili "ažuriranja".

Kako useEffect funkcionira na konceptualnoj razini

Osnovni potpis useEffect-a je vrlo jednostavan: useEffect(configuración, dependencias?)Predajete mu konfiguracijsku funkciju koja će se pokrenuti nakon što je komponenta iscrtana i, opcionalno, popis ovisnosti koji određuje kada se taj efekt treba ponoviti.

Konfiguracijska funkcija koncentrira logiku vašeg učinka: pretplatite se na nešto, pokrenite zahtjev, pokrenite interval, dodirnite DOM itd. Ta funkcija također može vratiti drugu funkciju čišćenja koju će React izvršiti kada je vrijeme za poništavanje onoga što ste učinili: otkazivanje vremenskog intervala, odjavu, prekid zahtjeva itd.

Drugi argument useEffect-a je poznati niz ovisnostiTamo trebate navesti sve "reaktivne" vrijednosti koje koristite unutar efekta: props, state i sve varijable ili funkcije definirane izravno unutar tijela komponente. React uspoređuje taj niz s onim iz prethodnog renderiranja koristeći Object.isAko se bilo koja ovisnost promijeni, očistite stari efekt i pokrenite novi.

Ako ne proslijedite niz ovisnosti, useEffect se izvršava nakon svakog renderiranja.Ako proslijedite prazan niz []Efekt se izvršava samo jednom prilikom sastavljanja i briše se prilikom rastavljanja, emulirajući moment componentDidMount / componentWillUnmountA ako prenesete specifične ovisnosti, učinak se aktivira samo kada se jedna od tih vrijednosti promijeni.

Prvi koraci: kombiniranje useState i useEffect

Klasičan primjer za razumijevanje odnosa između dva Hooka je tipičan brojač koji ažurira naslov dokumenta.. S useState Vi upravljate brojem klikova i pomoću useEffect ti se promijeni document.title nakon svakog renderiranja:

Ključno je da je useEffect definiran unutar komponenteStoga, možete izravno pročitati trenutno stanje i svojstva zahvaljujući JavaScript closures. Ne trebate posebne React API-je za pristup stanju unutar efekta; sve je unutar opsega funkcije.

  Popravak: pogreška "Audio tvrtke ne odgovaraju" u Home Home Windows 10

Nadalje, React ne koristi istu funkciju efekta između renderiranja: generirate novu funkciju sa svakim renderiranjem.To je namjerno: svaki efekt je povezan s renderom u kojem je stvoren, a kada React otkrije promjene u ovisnostima, zamjenjuje jedan efekt drugim, prvo čisteći prethodni. Ovaj model olakšava razumijevanje koje vrijednosti svaki efekt vidi u bilo kojem trenutku.

Još jedan važan detalj je da efekti ne blokiraju slikanje sučelja.React prvo ažurira DOM i omogućuje pregledniku da renderira, a zatim izvršava useEffectZa većinu slučajeva (zahtjevi, drvaitd.) To poboljšava osjećaj fluidnosti. Ako ikada trebate nešto učiniti sinkronizirano neposredno prije nego što korisnik vidi zaslon (na primjer, izmjeriti i promijeniti položaj opisa alata), tada biste trebali koristiti useLayoutEffect, koji dijeli API, ali se pokreće prije slikanja.

Vrste učinaka: sa i bez čišćenja

Nisu sve nuspojave jednake: neki se efekti pokrenu i to je to, dok drugi zahtijevaju eksplicitno čišćenje.Razlikovanje ove dvije vrste ključno je za izbjegavanje ostavljanja stvari neriješenih u sjećanju ili čudnih ponašanja.

Efekti bez čišćenja su oni kod kojih ne ostavljate ništa "otvoreno".Na primjer, pisanje u zapisnik, jednokratni zahtjev i spremanje rezultata u stanje, pokretanje samoupravljajuće animacije ili jednokratna modifikacija DOM-a. Što se tiče životnog ciklusa, oni ovise samo o componentDidMount / componentDidUpdate i ne zahtijevaju ništa od toga componentWillUnmount.

Tipičan primjer bi bio korištenje navigator.geolocation.getCurrentPosition nakon što je komponenta renderiranaZatražite lokaciju, ažurirate stanje s geografskom širinom i dužinom, React ponovno renderira i to je to. Ne ostavljate permanentnog slušača, tako da ne morate ništa čistiti prilikom demontiranja komponente.

Efekti čišćenja pojavljuju se kada je vaša komponenta trajno spojena na vanjski sustav.To uključuje pretplate na websockete ili chat API, DOM slušače događaja, ponavljajuće intervale ili vremenska ograničenja itd. U tim slučajevima, ako ne počistite prilikom odspajanja ili promjene ovisnosti, doći će do curenja memorije ili neočekivanog ponašanja.

React-ov idiomatski način rješavanja tog čišćenja je vraćanje funkcije iz efekta.Ova će se funkcija izvršavati svaki put kada je potrebno "demontirati" efekt: kada se komponenta ukloni iz DOM-a ili kada se promijene ovisnosti i stari efekt treba zamijeniti novim. Tipičan primjer je brojač s setInterval koji se čisti s clearInterval u povratku učinka.

useEffect primijenjen na globalne događaje i pretplate

Vrlo česta upotreba useEffect-a je pretplata na globalne događaje preglednika.Kao resize del window o keydown del documentU tim slučajevima, potrebno se povezati s događajem prilikom postavljanja komponente i odspojiti prilikom njezinog rastavljanja kako biste izbjegli nakupljanje slušača.

Uzorak je uvijek isti: dodajete slušače unutar efekta i uklanjate ih u funkciji čišćenja.Osim toga, ako želite da se ta pretplata kreira samo jednom, prosljeđujete prazan niz ovisnosti. [] kako se ne bi ponavljalo u svakom renderiranju.

Isti pristup primjenjuje se na integracije s vanjskim API-jima, SDK-ovima trećih strana ili bilo kojim sustavom koji vas prisiljava na "povezivanje" dok je komponenta vidljiva.Povezuješ se u funkciji za postavljanje efekta, a odspajaš u funkciji čišćenja, vjerujući da će React pozivati ​​obje po potrebi kako se ovisnosti mijenjaju.

U razvojnom načinu rada i sa strogim načinom rada, React izvodi dodatni prolaz konfiguracije i čišćenja odmah nakon montiranja.To je svojevrsni test opterećenja kako biste osigurali da vaša logika čišćenja zapravo poništava sve što konfiguracija radi. Ako primijetite čudno ponašanje samo u razvoju, to je obično zato što vaše čišćenje nije uspjelo.

HTTP zahtjevi i uvjeti utrke s useEffect

Drugi vrlo čest scenarij za useEffect je slanje HTTP zahtjeva kada se promijeni neki prop ili dio stanja.Na primjer, učitavanje korisničkih podataka kada se oni promijene userId ili dohvatiti informacije o Pokémonu kada se ime u rekvizitima ažurira.

Opća ideja je: definirate efekt koji pokreće asinhronu funkciju, ažurirate stanje s primljenim podacima i u polju ovisnosti navedete o kojim vrijednostima ovisi taj zahtjev.Ako želite da se aktivira samo tijekom vožnje, preskočite ovaj korak. []Ako želite da se pokreće svaki put kada se nešto promijeni userId, uključujete userId u nizu.

  Kako zakazati i upravljati automatskim zadacima pomoću schtasksa u sustavu Windows

Jedan delikatan detalj je što se događa ako se komponenta ukloni prije nego što zahtjev odgovori.. Da u then ili nakon await poziv na setState Što se tiče komponente koja više nije montirana, možete naići na upozorenja ili, još gore, ažuriranja statusa o zombi komponentama.

Uobičajeni obrazac za izbjegavanje ovoga je korištenje interne zastavice (na primjer, isMounted o ignore)Definiraš to u učinku, stavljaš to u truei u funkciji čišćenja postavite ga na falseUnutar asinhrone funkcije, neposredno prije pozivanja setState, provjeravate je li zastavica još uvijek na trueAko već jeste falsePreskačete ažuriranje. To također pomaže u izbjegavanju uvjeta utrke kada se više zahtjeva može riješiti drugačijim redoslijedom od onog kojim su poslani.

Druga, modernija opcija je korištenje AbortControllera ako API koji koristite to podržava.tako da funkcija čišćenja poziva abort() i obećanje zahtjeva se odbija bez pokušaja utjecaja na stanje. U svakom slučaju, logika otkazivanja ili ignoriranja odgovora mora biti inherentna samom učinku.

Višestruki pozivi funkcije useEffect u istoj komponenti

Jedna od prednosti Hookova je ta što vam omogućuju odvajanje logike prema onome što radi, a ne prema metodi životnog ciklusa u koju treba biti smještena.Nema ograničenja pri korištenju više useEffect u istoj komponenti.

To znači da možete imati jedan efekt za upravljanje naslovom dokumenta, drugi za pretplatu na chat i treći za osluškivanje događaja pomicanja.Svaki sa svojim vlastitim ovisnostima i logikom čišćenja, React će ih sve izvršiti redoslijedom kojim se pojavljuju u komponenti.

U usporedbi s klasama, gdje se mnogo nepovezane logike na kraju pomiješalo u istim metodama životnog ciklusa, Hookovi vas potiču na podjelu po odgovornostima.Jedan efekt = jedna specifična svrha. Ako jedan efekt počne raditi nekoliko različitih stvari, vjerojatno je vrijeme da ga podijelite na nekoliko.

Ovaj obrazac postaje još moćniji kada te efekte enkapsulirate u prilagođene hooks-ove. (na primjer, useWindowSize, useChatStatusitd.), ali čak i bez odlaska tako daleko dobivate čitljivost korištenjem više malih efekata umjesto jednog gigantskog.

Niz ovisnosti: reaktivnost i performanse

Niz ovisnosti je ono što useEffect čini moćnim i izvor mnogih glavobolja.Opće pravilo je jednostavno: svaka reaktivna vrijednost koju koristite unutar efekta mora se pojaviti u tom nizu. Reaktivne vrijednosti su svojstva, stanja i varijable ili funkcije definirane unutar komponente.

Ne radi se o "odabiru" ovisnosti kako bi se efekt manje izvodio, već o iskrenom opisivanju o kojim vrijednostima logika efekta ovisi.Ako je vlakno od eslint-plugin-react-hooks Pravilno je konfiguriran; upozorit će vas kada nešto izostavite ili dodate nešto nepotrebno.

Ako želite ukloniti ovisnost, to ne radite utišavanjem upozorenja; to radite promjenom koda tako da vrijednost više nije reaktivna.Na primjer, ako koristite konstantu serverUrl Budući da se nikada ne mijenja, možete ga premjestiti izvan tijela komponente. Na taj način prestaje biti reaktivna vrijednost i možete ga ukloniti iz niza bez obmanjivanja Reacta.

Kada efekt očita reaktivnu vrijednost, obično želite da reagira na te promjene.To znači dodavanje u niz. Ali ponekad želite pročitati "trenutnu" vrijednost nečega (poput košarice za kupnju) bez promjena na tom nečemu koje ponovno pokreću efekt. Za te slučajeve, React uvodi koncept "efektnih događaja" (poput useEffectEvent), koji enkapsuliraju nereaktivni kod koji može pročitati posljednju vrijednost bez da postane ovisnost.

Za poboljšanje performansi, tipičan obrazac je ograničavanje niza ovisnosti na minimum.Umjesto da efekt ostavimo bez drugog argumenta (koji ga pokreće nakon svakog renderiranja), prosljeđujemo niz samo s vrijednostima koje bi ga zapravo trebale pokrenuti. Ako se ovisnosti ne promijene između renderiranja, React preskače čišćenje i postavljanje, a efekt se ne izvršava ponovno.

  Vodič korak po korak do financijske neovisnosti: Ženske financije

Rješavanje uobičajenih problema s useEffectom

Jedna od najčešćih pogrešaka je završiti s efektom koji se izvodi u beskonačnoj petlji.To se obično događa kada ažurirate stanje unutar samog efekta, stanje koje je dio niza ovisnosti. Efekt mijenja stanje, stanje pokreće renderiranje, renderiranje ponovno izvršava efekt i ciklus počinje ispočetka.

Da biste prekinuli tu petlju, provjerite zašto ažurirate to stanje iz efektaAko ne sinkronizirate s vanjskim sustavom, možda vam useEffect neće ni trebati: mnoge se stvari mogu obraditi izravno u renderu. Ako sinkronizirate s nečim vanjskim, provjerite ovisi li ažuriranje stanja samo o stvarnim promjenama i ne pokreće li se svaki put.

Drugi česti izvor problema su ovisnosti koje se mijenjaju sa svakim renderiranjem, a da vi to ne primijetite.Stvaranje inline objekata ili funkcija u JSX-u i njihovo korištenje u efektu uvijek će rezultirati drugačijim nizom ovisnosti, jer svako renderiranje generira novu referencu. Da biste to izbjegli, možete premjestiti stvaranje ovih objekata na sam efekt ili, kao krajnje rješenje, stabilizirati ih s useMemo / useCallback.

Također je uobičajeno iznenaditi se kada se vidi da funkcija čišćenja radi čak i kada je komponenta još uvijek na ekranu.To je normalno: React čisti prethodni efekt prije primjene novog svaki put kada se promijene ovisnosti. A u razvoju, sa StrictModeom, također izvodi dodatni ciklus konfiguracije i čišćenja odmah nakon montiranja.

Konačno, ako je vaš efekt vizualan i primijetite treperenje prije nego što se primijeni, provjerite je li vizualno.Možda ćete morati prijeći na useLayoutEffect kako bi se prisilio na pokretanje prije nego što preglednik počne slikati. To je alat koji treba koristiti štedljivo, samo kada stvarno trebate blokirati slikanje dok se mjerenje ili pozicioniranje ne dovrši.

useEffect i renderiranje na strani poslužitelja (SSR)

Važan detalj kod aplikacija za renderiranje na strani poslužitelja je da se efekti izvode samo na klijentu.Tijekom SSR-a, React generira početni HTML, ali ne pokreće efekte. Oni se aktiviraju kasnije, kada se aplikacija hidrira u pregledniku.

To znači da bilo koja logika unutar useEffect-a koja se oslanja na API-je preglednika (kao što je localStorage o window) je siguran od poslužiteljaJer se neće tamo izravno pokrenuti. Ono što morate osigurati jest da je prvo renderiranje (ono koje se izvodi na poslužitelju, a zatim ponavlja na klijentu) determinističko i da ne čita ništa što postoji samo u pregledniku.

Ako želite prikazati različit sadržaj na poslužitelju i klijentu, uobičajeni obrazac je korištenje stanja poput didMountU početku je u falsei u useEffect s [] stavio si ga trueDok je vrijednost false (netočna), prikazuje se "sigurna" verzija komponente; kada postane true, tada se iz nje može čitati. localStorage, prilagodite DOM itd. Međutim, pokušajte osigurati da vizualna promjena ne bude previše iritantna za korisnike sa sporim vezama.

Općenito, što više svoje stablo komponenti učinite neovisnim o okruženju, to ćete imati manje iznenađenja pri kombiniranju SSR-a s Hookovima.Rezervirajte useEffect za stvarnu integraciju s vanjskim sustavima, što je i njegova namjena.

Savladavanje useState i useEffect uključuje internalizaciju činjenice da se komponente "ponovno stvaraju" pri svakom renderiranju, da efekti pripadaju određenom životnom ciklusu i da niz ovisnosti opisuje odnos između vašeg koda i reaktivnih podataka.Kada internalizirate taj mentalni model, osjećaj mračne magije nestaje i počinjete s lakoćom koristiti ove Hookove, pišući deklarativnije, čišće i lakše održavajuće komponente, čak i u velikim React aplikacijama.