Ahoj světe 👋
V tomto článku uvidíme pořadí, ve kterém se liší useEffect
proběhnou zpětná volání a čištění. Uvidíme také, jak se to liší, když se aplikace připojuje, odpojuje a aktualizuje.
Každá komponenta má tři fáze:
- Připojit
- Aktualizovat
- Odpojit
Montáž – tok háčků
V této fázi se komponenta zpočátku připojuje na stránku.
V této fázi je tok háčků následující:
- Spouštějte líné inicializátory
- Léné inicializátory jsou funkce, které předáváme
useState
auseReducer
. Tyto funkce budou spuštěny pouze v této fázi připojení.
- Léné inicializátory jsou funkce, které předáváme
- Vykreslení
- Tady jsou všechny
useState
jsou přítomny háčky a další věci.
- Tady jsou všechny
- Reagovat na aktualizace DOM
- Aktualizace modelu DOM není totéž, co prohlížeč maluje obrazovku.
- Spusťte efekty rozvržení
- Efekty rozložení uvidíme v budoucích článcích.
- Prohlížeč vybarví obrazovku
- Spustit efekty
Aktualizace – tok háčků
V této fázi dochází k aktualizaci komponenty.
K aktualizaci může dojít ze všech následujících důvodů:
- Rodič komponenty se znovu vykreslí
- Změny stavu komponenty
- Změny kontextu
V této fázi je tok háčků následující:
- Vykreslit
- Reagovat na aktualizace DOM
- Efekty rozvržení čištění
- (Jako
useEffect
)useLayoutEffect
má také fázi čištění.
- (Jako
- Spusťte efekty rozvržení
- Prohlížeč vybarví obrazovku
- Efekty čištění
- Spustit efekty
Jak můžete vidět, je to podobné tomu, co jsme viděli pro fázi připojení, kromě toho, že má také Cleanup Layout Effects
a Cleanup Effects
.
Odpojit – tok háčků
V této fázi se komponenta odpojí ze stránky.
V této fázi je tok háčků následující:
- Efekty rozvržení čištění
- Efekty čištění
V této fázi budou probíhat pouze čištění.
Typy použitíEfekt zpětných volání
Než uvidíme příklad, podívejme se na 3 různé typy useEffect
zpětná volání.
- useEffect bez závislostí
- useEffect s prázdnými závislostmi
- useEffect s některými závislostmi
1. useEffect bez závislostí
useEffect(() => {
console.log('useEffect(() => {})') // Line 1
return () => {
console.log('useEffect(() => {}) cleanup') // Line 2
}
})
Toto useEffect
zpětné volání nemá žádné závislosti.
- Funkce zpětného volání (Řádek 1) bude spuštěna, když:
- Komponenta je připojena
- Komponenta je aktualizována
- Funkce čištění (řádek 2) bude spuštěna, když:
- Komponenta je aktualizována
- Součást je odpojena
2. useEffect s prázdnými závislostmi
useEffect(() => {
console.log('useEffect(() => {}, [])') // Line 1
return () => {
console.log('useEffect(() => {}, []) cleanup') // Line 2
}
}, [])
Toto useEffect
zpětné volání má prázdné závislosti.
- Funkce zpětného volání (Řádek 1) bude spuštěna, když:
- Komponenta je připojena
- Funkce čištění (řádek 2) bude spuštěna, když:
- Součást je odpojena
Poznámka: Toto useEffect
zpětné volání nebude provedeno, když se komponenta aktualizuje kvůli prázdnému poli závislostí.
3. useEffect s některými závislostmi
useEffect(() => {
console.log('useEffect(() => {}, [count])') // Line 1
return () => {
console.log('useEffect(() => {}, [count]) cleanup') // Line 2
}
}, [count])
Toto useEffect
zpětné volání má jednu nebo více závislostí.
- Funkce zpětného volání (Řádek 1) bude spuštěna, když:
- Komponenta je připojena
- Jakákoli závislost se změní – v tomto případě, když se změní počet.
- Funkce čištění (řádek 2) bude spuštěna, když:
- Jakákoli závislost se změní – v tomto případě, když se změní počet.
- Součást je odpojena
Příklad
Zvažte níže uvedený příklad
import React from "react";
function App() {
console.log("App: render start");
const [showChild, setShowChild] = React.useState(() => {
console.log("App: useState(() => false)");
return false;
});
console.log(`App: showChild = ${showChild}`);
React.useEffect(() => {
console.log("App: useEffect(() => {})");
return () => {
console.log("App: useEffect(() => {}) cleanup");
};
});
React.useEffect(() => {
console.log("App: useEffect(() => {}, [])");
return () => {
console.log("App: useEffect(() => {}, []) cleanup");
};
}, []);
React.useEffect(() => {
console.log("App: useEffect(() => {}, [showChild])");
return () => {
console.log("App: useEffect(() => {}, [showChild]) cleanup");
};
}, [showChild]);
const element = (
<>
<label>
<input
type="checkbox"
checked={showChild}
onChange={(e) => setShowChild(e.target.checked)}
/>{" "}
show child
</label>
<div>
{showChild ? <Child /> : null}
</div>
</>
);
console.log("App: render end");
return element;
}
import React from "react";
function Child() {
console.log(" Child: render start");
const [count, setCount] = React.useState(() => {
console.log(" Child: useState(() => 0)");
return 0;
});
console.log(` Child: count = ${count}`);
React.useEffect(() => {
console.log(" Child: useEffect(() => {})");
return () => {
console.log(" Child: useEffect(() => {}) cleanup");
};
});
React.useEffect(() => {
console.log(" Child: useEffect(() => {}, [])");
return () => {
console.log(" Child: useEffect(() => {}, []) cleanup");
};
}, []);
React.useEffect(() => {
console.log(" Child: useEffect(() => {}, [count])");
return () => {
console.log(" Child: useEffect(() => {}, [count]) cleanup");
};
}, [count]);
const element = (
<button onClick={() => setCount((previousCount) => previousCount + 1)}>
{count}
</button>
);
console.log(" Child: render end");
return element;
}
- máme
App
komponenta aChild
komponenta. App
komponenta má stav, který rozhoduje, zda se má zobrazitChild
komponent nebo ne.Child
komponenta mácount
stavu.Child
má tlačítko pro aktualizacicount
.- Oba
App
aChild
má tři typyuseEffect
zpětná voláníuseEffect
bez závislostíuseEffect
s prázdnými závislostmiuseEffect
s jednou nebo více závislostmi.
Uvidíme, jak bude tok vypadat pro každý z následujících kroků:
- Aplikace je připojena
- Dítě je připojeno aktualizací stavu v aplikaci
- Dítě je aktualizováno aktualizací počtu v Child
- Dítě je odpojeno aktualizací stavu v aplikaci
1. Aplikace je připojena
Zde je App
je ve fázi montáže, takže z diagramu by pořadí mělo být
- ✅ Spouštějte líné inicializátory aplikace
- ✅ Vykreslení aplikace
- ✅ Reagovat na aktualizace DOM aplikace
- ❌ Efekty vyčištění rozvržení aplikace
- ✅ Spusťte efekty rozložení aplikace
- ✅ Prohlížeč vykreslí obrazovku aplikace
- ❌ Účinky čištění aplikace
- ✅ Spusťte Efekty aplikace
Když App
je připojen, vidíme následující protokoly konzoly.
- Aplikace:zahájení vykreslování
- Zahájí se vykreslování aplikace.
- App:useState(() => false)
- Probíhá spuštění líného inicializátoru aplikace.
- Aplikace:showChild =false
- Vykreslování aplikací.
- Aplikace:konec vykreslení
- Vykreslování aplikací je dokončeno.
- Aplikace:useEffect(() => {})
- Aplikace
useEffect
bez závislostí.
- Aplikace
- Aplikace:useEffect(() => {}, [])
- Aplikace
useEffect
s prázdnými závislostmi. - Toto je voláno, protože toto je fáze připojení
App
komponentu a ve fázi připojení všechnyuseEffect
budou volána zpětná volání.
- Aplikace
- Aplikace:useEffect(() => {}, [showChild])
- Aplikace
useEffect
sshowChild
jak se provádí závislost. - Toto je voláno, protože toto je fáze připojení
App
komponentu a ve fázi připojení všechnyuseEffect
budou volána zpětná volání.
- Aplikace
Poznámky:
- Všechny
useEffect
zpětná volání se provedou při počátečním připojení komponenty useEffect
zpětná volání budou spuštěna v pořadí, v jakém se objeví.
2. Child je připojen aktualizací stavu v App
Klikneme na show child
zaškrtávací políčko. Tím se připojí Child
komponenta.
Zde Child
bude ve fázi připojení a App
bude ve fázi aktualizace.
Podle diagramu, objednávka pro Child
bude
- ✅ Spouštět líné inicializátory Child
- ✅ Vykreslení dítěte
- ✅ Reagovat na aktualizace DOM of Child
- ❌ Efekty rozvržení Vyčištění dítěte
- ✅ Spusťte aplikaci Layout Effects of Child
- ✅ Prohlížeč vykreslí obrazovku dítěte
- ❌ Účinky čištění dítěte
- ✅ Run Effects of Child
A pro App
,
- ❌ Spouštějte líné inicializátory aplikace
- ✅ Vykreslení aplikace
- ✅ Reagovat na aktualizace DOM aplikace
- ✅ Vyčištění efektů rozvržení aplikace
- ✅ Spusťte efekty rozložení aplikace
- ✅ Prohlížeč vykreslí obrazovku aplikace
- ✅ Čistící efekty aplikace
- ✅ Spusťte Efekty aplikace
Uvidíme následující protokoly konzoly.
- Aplikace:zahájení vykreslování
- Zahájí se vykreslování aplikace.
- Lazy inicializátor NEBUDE být spuštěn nyní. Běží pouze na počátečním připojení.
- Aplikace:showChild =true
- Vykreslování aplikací.
- Aplikace:konec vykreslení
- Vykreslování aplikací je dokončeno.
- Dítě:začátek vykreslování
- Child je připojen a Child se začne vykreslovat.
- Dítě:useState(() => 0)
- Child lazy inicializátor se spouští, protože toto je fáze připojení Child.
- Dítě:počet =0
- Dětské vykreslování.
- Dítě:konec vykreslení .
- Podřízené vykreslování se dokončí.
- Aplikace:useEffect(() => {}) vyčištění
- App useEffect bez čištění závislostí.
- Aplikace:useEffect(() => {}, [showChild]) vyčištění
- App useEffect s
showChild
vyčištění závislostí. - Toto čištění se děje z důvodu
showChild
se zde aktualizuje.
- App useEffect s
- Dítě:useEffect(() => {})
- Probíhá podřízený useEffect bez závislostí.
- Dítě:useEffect(() => {}, [])
- Probíhá provádění Child useEffect s prázdnými závislostmi.
- Toto je voláno, protože toto je fáze připojení
Child
komponentu a ve fázi připojení všechnyuseEffect
budou volána zpětná volání.
- Dítě:useEffect(() => {}, [počet])
- Child useEffect s
count
jako závislost se provádí. - Toto je voláno, protože toto je fáze připojení
Child
komponentu a ve fázi připojení všechnyuseEffect
budou volána zpětná volání.
- Child useEffect s
- Aplikace:useEffect(() => {})
- Probíhá provádění aplikace useEffect bez závislostí.
- Aplikace:useEffect(() => {}, [showChild])
- App useEffect s
showChild
se spouští závislosti. - Toto je voláno kvůli
showChild
byl aktualizován.
- App useEffect s
Poznámky:
- Při vykreslování
App
komponenta, máme<Child />
v jeho označení. Ale můžete vidětChild
render začíná zaApp
render končí. - Je to proto, že
<Child />
není totéž jako voláníChild
funkce. Je to v podstatě voláníReact.createElement(Child)
. - React začne volat pouze
Child
když je čas na vykreslení.
3. Dítě je aktualizováno aktualizací počtu v Child
Klikneme na count
tlačítko pro aktualizaci count
přítomen v Child
.
Zde Child
bude ve fázi aktualizace a App
nemá žádnou změnu.
Podle diagramu, objednávka pro Child
bude
- ❌ Spouštět líné inicializátory Child
- ✅ Vykreslení dítěte
- ✅ Reagovat na aktualizace DOM of Child
- ✅ Efekty rozvržení Vyčištění aplikace Child
- ✅ Spusťte aplikaci Layout Effects of Child
- ✅ Prohlížeč vykreslí obrazovku dítěte
- ✅ Cleanup Effects of Child
- ✅ Run Effects of Child
Uvidíme následující protokoly konzoly
- Dítě:začátek vykreslování
- Spustí se vykreslování dítěte.
- Dítě:počet =1
- Dětské vykreslení
- Dítě:konec vykreslení
- Podřízené vykreslování končí.
- Dítě:useEffect(() => {}) vyčištění
- Child useEffect bez čištění závislostí.
- Dítě:useEffect(() => {}, [počet]) vyčištění
- Dítě useEffect s
count
jako vyčištění závislostí. - Toto se volá, protože
count
aktualizoval(a).
- Dítě useEffect s
- Dítě:useEffect(() => {})
- Probíhá podřízený useEffect bez závislostí.
- Dítě:useEffect(() => {}, [počet])
- Dítě useEffect s
count
jako závislost se provádí. - Toto se volá kvůli
count
byl aktualizován.
- Dítě useEffect s
4. Dítě je odpojeno aktualizací stavu v aplikaci
Klikněte na show child
zaškrtávací políčko pro odpojení Child
komponenta.
Zde Child
bude ve fázi odpojení a App
bude ve fázi aktualizace
Podle diagramu, objednávka pro Child
bude
- ❌ Spouštět líné inicializátory Child
- ❌ Vykreslení dítěte
- ❌ Reagovat na aktualizace DOM of Child
- ✅ Efekty rozvržení Vyčištění aplikace Child
- ❌ Spusťte efekty rozvržení dítěte
- ❌ Prohlížeč vykreslí obrazovku dítěte
- ✅ Cleanup Effects of Child
- ❌ Spustit Effects of Child
A pro aplikaci
- ❌ Spouštějte líné inicializátory aplikace
- ✅ Vykreslení aplikace
- ✅ Reagovat na aktualizace DOM aplikace
- ✅ Vyčištění efektů rozvržení aplikace
- ✅ Spusťte efekty rozložení aplikace
- ✅ Prohlížeč vykreslí obrazovku aplikace
- ✅ Čistící efekty aplikace
- ✅ Spusťte Efekty aplikace
Uvidíme následující protokoly konzoly
- Aplikace:spuštění vykreslování
- Zahájí se vykreslování aplikace.
- Aplikace:showChild =false
- Vykreslování aplikací
- Aplikace:konec vykreslení
- Vykreslování aplikací končí
- Dítě:useEffect(() => {}) vyčištění
- Child useEffect bez čištění závislostí
- Dítě:useEffect(() => {}, []) vyčištění
- Efekt použití podřízeného uživatele s vyčištěním prázdných závislostí
- Toto se zde volá, protože ve fázi odpojení a ve fázi odpojení budou volána všechna čištění.
- Dítě:useEffect(() => {}, [počet]) vyčištění
- Dítě useEffect s
count
jako vyčištění závislosti - Toto se zde volá, protože ve fázi odpojení a ve fázi odpojení budou volána všechna čištění.
- Dítě useEffect s
- Aplikace:useEffect(() => {}) vyčištění
- App useEffect bez čištění závislostí
- Aplikace:useEffect(() => {}, [showChild]) vyčištění
- App useEffect s
showChild
jako vyčištění závislosti. - Toto je voláno kvůli
showChild
aktualizoval zde.
- App useEffect s
- Aplikace:useEffect(() => {})
- Probíhá spuštění aplikace useEffect bez závislostí
- Aplikace:useEffect(() => {}, [showChild])
- App useEffect s
showChild
jako závislost se provádí - Toto se volá kvůli
showChild
aktualizoval zde.
- App useEffect s
A nakonec, když App
komponenta se také odpojí, cleanup
ze všech App
useEffect
s bude voláno.
Odkazy a reference:
- Tok háčků v
EpicReact.Dev
od Kenta C. Doddse - Pochopte tok React Hook Flow v
The Beginners Guide To React
od Kenta C. Doddse - Hook Flow Diagram
Co bude dál?
V příštím článku se podíváme na to, co znamená lifting state a colocating state v Reactu. A také uvidíme, kdy budou užitečné.
Až příště 👋
Pokud se vám tento článek líbil, podívejte se
- React Hooks:Správa stavu pomocí useState Hook
- Jak vytvořit opakovaně použitelný LocalStorage Hook
- Snadné zjištění vnějšího kliknutí pomocí useRef Hook
Pokud máte nějaké komentáře, zanechte je prosím níže nebo mě můžete také @me na Twitteru (@pbteja1998), nebo mě neváhejte sledovat.