Životní cyklus komponenty React Hooks

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:

  1. Připojit
  2. Aktualizovat
  3. 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í:

  1. Spouštějte líné inicializátory
    • Léné inicializátory jsou funkce, které předáváme useState a useReducer . Tyto funkce budou spuštěny pouze v této fázi připojení.
  2. Vykreslení
    • Tady jsou všechny useState jsou přítomny háčky a další věci.
  3. Reagovat na aktualizace DOM
    • Aktualizace modelu DOM není totéž, co prohlížeč maluje obrazovku.
  4. Spusťte efekty rozvržení
    • Efekty rozložení uvidíme v budoucích článcích.
  5. Prohlížeč vybarví obrazovku
  6. 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í.
  • 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í.

  1. useEffect bez závislostí
  2. useEffect s prázdnými závislostmi
  3. 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 a Child komponenta.
  • App komponenta má stav, který rozhoduje, zda se má zobrazit Child komponent nebo ne.
  • Child komponenta má count stavu.
  • Child má tlačítko pro aktualizaci count .
  • Oba App a Child má tři typy useEffect zpětná volání
    • useEffect bez závislostí
    • useEffect s prázdnými závislostmi
    • useEffect s jednou nebo více závislostmi.

Uvidíme, jak bude tok vypadat pro každý z následujících kroků:

  1. Aplikace je připojena
  2. Dítě je připojeno aktualizací stavu v aplikaci
  3. Dítě je aktualizováno aktualizací počtu v Child
  4. 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

  1. ✅ Spouštějte líné inicializátory aplikace
  2. ✅ Vykreslení aplikace
  3. ✅ Reagovat na aktualizace DOM aplikace
  4. ❌ Efekty vyčištění rozvržení aplikace
  5. ✅ Spusťte efekty rozložení aplikace
  6. ✅ Prohlížeč vykreslí obrazovku aplikace
  7. ❌ Účinky čištění aplikace
  8. ✅ Spusťte Efekty aplikace

Když App je připojen, vidíme následující protokoly konzoly.

  1. Aplikace:zahájení vykreslování
    • Zahájí se vykreslování aplikace.
  2. App:useState(() => false)
    • Probíhá spuštění líného inicializátoru aplikace.
  3. Aplikace:showChild =false
    • Vykreslování aplikací.
  4. Aplikace:konec vykreslení
    • Vykreslování aplikací je dokončeno.
  5. Aplikace:useEffect(() => {})
    • Aplikace useEffect bez závislostí.
  6. 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šechny useEffect budou volána zpětná volání.
  7. Aplikace:useEffect(() => {}, [showChild])
    • Aplikace useEffect s showChild 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šechny useEffect budou volána zpětná volání.

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

  1. ✅ Spouštět líné inicializátory Child
  2. ✅ Vykreslení dítěte
  3. ✅ Reagovat na aktualizace DOM of Child
  4. ❌ Efekty rozvržení Vyčištění dítěte
  5. ✅ Spusťte aplikaci Layout Effects of Child
  6. ✅ Prohlížeč vykreslí obrazovku dítěte
  7. ❌ Účinky čištění dítěte
  8. ✅ Run Effects of Child

A pro App ,

  1. ❌ Spouštějte líné inicializátory aplikace
  2. ✅ Vykreslení aplikace
  3. ✅ Reagovat na aktualizace DOM aplikace
  4. ✅ Vyčištění efektů rozvržení aplikace
  5. ✅ Spusťte efekty rozložení aplikace
  6. ✅ Prohlížeč vykreslí obrazovku aplikace
  7. ✅ Čistící efekty aplikace
  8. ✅ Spusťte Efekty aplikace

Uvidíme následující protokoly konzoly.

  1. 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í.
  2. Aplikace:showChild =true
    • Vykreslování aplikací.
  3. Aplikace:konec vykreslení
    • Vykreslování aplikací je dokončeno.
  4. Dítě:začátek vykreslování
    • Child je připojen a Child se začne vykreslovat.
  5. Dítě:useState(() => 0)
    • Child lazy inicializátor se spouští, protože toto je fáze připojení Child.
  6. Dítě:počet =0
    • Dětské vykreslování.
  7. Dítě:konec vykreslení .
    • Podřízené vykreslování se dokončí.
  8. Aplikace:useEffect(() => {}) vyčištění
    • App useEffect bez čištění závislostí.
  9. 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.
  10. Dítě:useEffect(() => {})
    • Probíhá podřízený useEffect bez závislostí.
  11. 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šechny useEffect budou volána zpětná volání.
  12. 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šechny useEffect budou volána zpětná volání.
  13. Aplikace:useEffect(() => {})
    • Probíhá provádění aplikace useEffect bez závislostí.
  14. Aplikace:useEffect(() => {}, [showChild])
    • App useEffect s showChild se spouští závislosti.
    • Toto je voláno kvůli showChild byl aktualizován.

Poznámky:

  • Při vykreslování App komponenta, máme <Child /> v jeho označení. Ale můžete vidět Child render začíná za App 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

  1. ❌ Spouštět líné inicializátory Child
  2. ✅ Vykreslení dítěte
  3. ✅ Reagovat na aktualizace DOM of Child
  4. ✅ Efekty rozvržení Vyčištění aplikace Child
  5. ✅ Spusťte aplikaci Layout Effects of Child
  6. ✅ Prohlížeč vykreslí obrazovku dítěte
  7. ✅ Cleanup Effects of Child
  8. ✅ Run Effects of Child

Uvidíme následující protokoly konzoly

  1. Dítě:začátek vykreslování
    • Spustí se vykreslování dítěte.
  2. Dítě:počet =1
    • Dětské vykreslení
  3. Dítě:konec vykreslení
    • Podřízené vykreslování končí.
  4. Dítě:useEffect(() => {}) vyčištění
    • Child useEffect bez čištění závislostí.
  5. 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).
  6. Dítě:useEffect(() => {})
    • Probíhá podřízený useEffect bez závislostí.
  7. 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.

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

  1. ❌ Spouštět líné inicializátory Child
  2. ❌ Vykreslení dítěte
  3. ❌ Reagovat na aktualizace DOM of Child
  4. ✅ Efekty rozvržení Vyčištění aplikace Child
  5. ❌ Spusťte efekty rozvržení dítěte
  6. ❌ Prohlížeč vykreslí obrazovku dítěte
  7. ✅ Cleanup Effects of Child
  8. ❌ Spustit Effects of Child

A pro aplikaci

  1. ❌ Spouštějte líné inicializátory aplikace
  2. ✅ Vykreslení aplikace
  3. ✅ Reagovat na aktualizace DOM aplikace
  4. ✅ Vyčištění efektů rozvržení aplikace
  5. ✅ Spusťte efekty rozložení aplikace
  6. ✅ Prohlížeč vykreslí obrazovku aplikace
  7. ✅ Čistící efekty aplikace
  8. ✅ Spusťte Efekty aplikace

Uvidíme následující protokoly konzoly

  1. Aplikace:spuštění vykreslování
    • Zahájí se vykreslování aplikace.
  2. Aplikace:showChild =false
    • Vykreslování aplikací
  3. Aplikace:konec vykreslení
    • Vykreslování aplikací končí
  4. Dítě:useEffect(() => {}) vyčištění
    • Child useEffect bez čištění závislostí
  5. 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í.
  6. 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í.
  7. Aplikace:useEffect(() => {}) vyčištění
    • App useEffect bez čištění závislostí
  8. 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.
  9. Aplikace:useEffect(() => {})
    • Probíhá spuštění aplikace useEffect bez závislostí
  10. Aplikace:useEffect(() => {}, [showChild])
    • App useEffect s showChild jako závislost se provádí
    • Toto se volá kvůli showChild aktualizoval zde.

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.