Reaguj useEffecthaki


useEffectHook pozwala na wykonywanie efektów ubocznych w twoich komponentach .

Niektóre przykłady efektów ubocznych to: pobieranie danych, bezpośrednia aktualizacja DOM i liczniki czasu.

useEffectprzyjmuje dwa argumenty. Drugi argument jest opcjonalny.

useEffect(<function>, <dependency>)


Jako przykładu użyjmy timera.

Przykład:

Służy setTimeout()do odliczania 1 sekundy po wstępnym renderowaniu:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

Ale poczekaj!! Ciągle liczę, chociaż powinno liczyć tylko raz!

useEffectdziała na każdym renderze. Oznacza to, że gdy zmienia się liczba, następuje renderowanie, które następnie wyzwala inny efekt.

Nie tego chcemy. Istnieje kilka sposobów kontrolowania wystąpienia efektów ubocznych.

Powinniśmy zawsze uwzględniać drugi parametr, który akceptuje tablicę. Opcjonalnie możemy przekazać zależności useEffectw tej tablicy.

1. Nie przeszła żadna zależność:

useEffect(() => {
  //Runs on every render
});

2. Pusta tablica:

useEffect(() => {
  //Runs only on the first render
}, []);

3. Rekwizyty lub wartości stanów:

useEffect(() => {
  //Runs on the first render
  //And any time any dependency value changes
}, [prop, state]);

Aby rozwiązać ten problem, uruchommy ten efekt tylko przy początkowym renderowaniu.

Przykład:

Uruchom efekt tylko na początkowym renderowaniu:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  }, []); // <- add empty brackets here

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

Przykład:

Oto przykład useEffecthooka, który jest zależny od zmiennej. Jeśli countzmienna się zaktualizuje, efekt uruchomi się ponownie:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Counter() {
  const [count, setCount] = useState(0);
  const [calculation, setCalculation] = useState(0);

  useEffect(() => {
    setCalculation(() => count * 2);
  }, [count]); // <- add the count variable here

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>+</button>
      <p>Calculation: {calculation}</p>
    </>
  );
}

ReactDOM.render(<Counter />, document.getElementById('root'));

Jeśli istnieje wiele zależności, należy je uwzględnić w useEffecttablicy zależności.


w3schools CERTIFIED . 2022

Zostać certyfikowanym!

Uzupełnij moduły React, wykonaj ćwiczenia, podejdź do egzaminu i uzyskaj certyfikat w3schools!!

95 $ ZAPISZ

Czyszczenie efektów

Niektóre efekty wymagają oczyszczenia w celu zmniejszenia wycieków pamięci.

Limity czasu, subskrypcje, detektory zdarzeń i inne efekty, które nie są już potrzebne, należy usunąć.

Robimy to, dołączając funkcję powrotu na końcu useEffecthooka.

Przykład:

Wyczyść licznik czasu na końcu useEffecthaka:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
    setCount((count) => count + 1);
  }, 1000);

  return () => clearTimeout(timer)
  }, []);

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById("root"));

Uwaga: Aby wyczyścić timer, musieliśmy go nazwać.


Sprawdź się za pomocą ćwiczeń

Ćwiczenie:

Co musisz dodać do drugiego argumentu useEffecthooka, aby ograniczyć go do uruchamiania tylko przy pierwszym renderowaniu?

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    setData(getData())
  }, );

  return <DisplayData data={data} />;
}

ReactDOM.render(<App />, document.getElementById('root'));