Ganchos de useEffectreação


O useEffectGancho permite que você execute efeitos colaterais em seus componentes.

Alguns exemplos de efeitos colaterais são: buscar dados, atualizar diretamente o DOM e cronômetros.

useEffectaceita dois argumentos. O segundo argumento é opcional.

useEffect(<function>, <dependency>)


Vamos usar um temporizador como exemplo.

Exemplo:

Use setTimeout()para contar 1 segundo após a renderização inicial:

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

Mas espere!! Eu continuo contando mesmo que devesse contar apenas uma vez!

useEffecté executado em cada renderização. Isso significa que quando a contagem muda, uma renderização acontece, o que aciona outro efeito.

Não é isso que queremos. Existem várias maneiras de controlar quando os efeitos colaterais são executados.

Devemos sempre incluir o segundo parâmetro que aceita um array. Opcionalmente, podemos passar dependências para useEffectesse array.

1. Nenhuma dependência passada:

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

2. Uma matriz vazia:

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

3. Adereços ou valores de estado:

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

Então, para corrigir esse problema, vamos executar esse efeito apenas na renderização inicial.

Exemplo:

Execute o efeito apenas na renderização inicial:

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

Exemplo:

Aqui está um exemplo de um useEffectHook que é dependente de uma variável. Se a countvariável for atualizada, o efeito será executado novamente:

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 houver várias dependências, elas devem ser incluídas na useEffectmatriz de dependências.


w3schools CERTIFIED . 2022

Obter certificação!

Complete os módulos React, faça os exercícios, faça o exame e torne-se certificado w3schools!!

$ 95 INSCRIÇÃO

Limpeza do efeito

Alguns efeitos requerem limpeza para reduzir vazamentos de memória.

Tempos limite, assinaturas, ouvintes de eventos e outros efeitos que não são mais necessários devem ser descartados.

Fazemos isso incluindo uma função de retorno no final do useEffectHook.

Exemplo:

Limpe o cronômetro no final do useEffectGancho:

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: Para limpar o cronômetro, tivemos que nomeá-lo.


Teste-se com exercícios

Exercício:

O que você precisa adicionar ao segundo argumento de um useEffectHook para limitá-lo a ser executado apenas na primeira renderização?

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