Ganci di useEffectreazione


The useEffectHook ti consente di eseguire effetti collaterali nei tuoi componenti.

Alcuni esempi di effetti collaterali sono: recupero dei dati, aggiornamento diretto del DOM e timer.

useEffectaccetta due argomentazioni. Il secondo argomento è facoltativo.

useEffect(<function>, <dependency>)


Usiamo un timer come esempio.

Esempio:

Utilizzare setTimeout()per contare 1 secondo dopo il rendering iniziale:

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'));

Ma aspetta!! Continuo a contare anche se dovrebbe contare solo una volta!

useEffectviene eseguito su ogni rendering. Ciò significa che quando il conteggio cambia, si verifica un rendering, che quindi attiva un altro effetto.

Questo non è quello che vogliamo. Esistono diversi modi per controllare quando si verificano gli effetti collaterali.

Dovremmo sempre includere il secondo parametro che accetta un array. Possiamo opzionalmente passare le dipendenze useEffectin questo array.

1. Nessuna dipendenza superata:

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

2. Un array vuoto:

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

3. Props o valori di stato:

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

Quindi, per risolvere questo problema, eseguiamo questo effetto solo sul rendering iniziale.

Esempio:

Esegui solo l'effetto sul rendering iniziale:

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'));

Esempio:

Ecco un esempio di useEffectHook che dipende da una variabile. Se la countvariabile si aggiorna, l'effetto verrà eseguito di nuovo:

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'));

Se sono presenti più dipendenze, dovrebbero essere incluse useEffectnell'array delle dipendenze.


w3schools CERTIFIED . 2022

Ottieni la certificazione!

Completa i moduli React, fai gli esercizi, fai l'esame e diventa certificato w3schools!!

ISCRIVITI A $95

Pulizia degli effetti

Alcuni effetti richiedono la pulizia per ridurre le perdite di memoria.

Timeout, abbonamenti, listener di eventi e altri effetti non più necessari devono essere eliminati.

Lo facciamo includendo una funzione di ritorno alla fine di useEffectHook.

Esempio:

Pulisci il timer alla fine del useEffectgancio:

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"));

Nota: per cancellare il timer, abbiamo dovuto nominarlo.


Mettiti alla prova con gli esercizi

Esercizio:

Cosa è necessario aggiungere al secondo argomento di un useEffectHook per limitarlo all'esecuzione solo al primo rendering?

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'));