quarta-feira, novembro 27, 2024
Home Programação Loop Infinito + Linting Array de Dependências no useEffect

Loop Infinito + Linting Array de Dependências no useEffect

Porque muitas vezes ao colocar uma variável no Array de dependências do useEffect ocorre o Loop Infinito e como resolver?

O problema ocorre quando um valor no array de dependência é alterado durante a renderização do componente e causa uma nova renderização, que pode ser desnecessária. Isso pode levar a um loop infinito de renderizações.

Para resolver esse problema, podemos usar o useRef para armazenar uma referência a um valor que precisa ser usado dentro do useEffect, mas que não deve ser incluído no array de dependência.

Por exemplo, suponha que temos um componente que precisa buscar dados de uma API sempre que um botão é clicado. Usando useEffect para isso, poderíamos escrever algo como:

function MyComponent() {
  const [data, setData] = useState(null);
  const [buttonClicked, setButtonClicked] = useState(false);

  useEffect(() => {
    if (buttonClicked) {
      fetchData();
    }
  }, [buttonClicked]);

  const fetchData = async () => {
    const response = await fetch('https://my-api.com/data');
    const data = await response.json();
    setData(data);
  }

  return (
    <div>
      <button onClick={() => setButtonClicked(true)}>Fetch Data</button>
      {data && <p>{data}</p>}
    </div>
  )
}

Nesse exemplo, o useEffect é executado toda vez que o buttonClicked é alterado, o que faz com que a API seja chamada sempre que o botão é clicado. No entanto, se tivermos outros estados que afetam a renderização do componente, como um estado de filtro que não afeta a chamada da API, incluí-lo no array de dependência pode causar uma nova renderização desnecessária.

Nesse caso, podemos usar o useRef para armazenar uma referência a um valor que precisa ser usado dentro do useEffect, mas que não deve ser incluído no array de dependência. Podemos fazer isso adicionando uma referência buttonClickedRef usando o useRef, que não afeta a renderização do componente e garantir que ela seja sempre a mesma:

function MyComponent() {
  const [data, setData] = useState(null);
  const [buttonClicked, setButtonClicked] = useState(false);
  const buttonClickedRef = useRef(false);

  useEffect(() => {
    if (buttonClickedRef.current) {
      fetchData();
    }
  }, [buttonClickedRef]);

  const fetchData = async () => {
    const response = await fetch('https://my-api.com/data');
    const data = await response.json();
    setData(data);
  }

  return (
    <div>
      <button onClick={() => {
        setButtonClicked(true);
        buttonClickedRef.current = true;
      }}>Fetch Data</button>
      {data && <p>{data}</p>}
    </div>
  )
}

Aqui, ao clicar no botão, estamos atualizando o estado do buttonClicked como antes e também atualizando o buttonClickedRef.current para true. Como a referência não afeta a renderização do componente, não precisamos incluí-la no array de dependência do useEffect, e podemos usá-la para garantir que a chamada da API ocorra apenas quando o botão for clicado.

Uma outra forma de se resolver esta dor, mas lembre-se vai depender da forma como seu código estiver disposto

Uma outra forma de resolver o problema do useEffect que depende de um valor que não deve estar no array de dependência é usando uma função de atualização de estado em vez do valor diretamente.

Em vez de incluir o valor no array de dependência, podemos incluir a função de atualização de estado que altera o valor. Dessa forma, o useEffect sempre usará a versão mais recente da função, que sempre atualiza o valor correto.

Por exemplo, usando o mesmo exemplo anterior, podemos modificar o buttonClicked para ser um objeto com uma propriedade value, e usar uma função de atualização de estado para atualizá-lo. Isso nos permite incluir apenas a função setButtonClicked no array de dependência do useEffect:

function MyComponent() {
  const [data, setData] = useState(null);
  const [buttonClicked, setButtonClicked] = useState({ value: false });

  useEffect(() => {
    if (buttonClicked.value) {
      fetchData();
    }
  }, [setButtonClicked]);

  const fetchData = async () => {
    const response = await fetch('https://my-api.com/data');
    const data = await response.json();
    setData(data);
  }

  return (
    <div>
      <button onClick={() => setButtonClicked({ value: true })}>Fetch Data</button>
      {data && <p>{data}</p>}
    </div>
  )
}

Nesse exemplo, usamos uma função de atualização de estado em setButtonClicked para atualizar o valor de buttonClicked. Dessa forma, podemos incluir apenas a função setButtonClicked no array de dependência do useEffect. O valor real de buttonClicked é atualizado automaticamente pelo React sempre que a função setButtonClicked é chamada, garantindo que o useEffect sempre use o valor mais recente e atualizado.

Essa abordagem também pode ser útil em outros casos em que precisamos atualizar um estado com base em seu valor anterior, ou quando o estado é um objeto com várias propriedades e só queremos atualizar uma delas.

DEIXE UMA RESPOSTA

Por favor entre com seu comentário
Por favor insira o seu nome aqui

Últimos artigos

Entenda o que é refatoração de código

Porque a refatoração de código é tão importante na programação Melhora a qualidade do código: A refatoração ajuda a melhorar a qualidade do código,...

O que são Padrões de Projeto de Software

O que são Padrões de Projeto de Software Design patterns, ou padrões de projeto de software, são soluções comprovadas e testadas para problemas comuns que...

Winston NodeJS Logger

O que são logs de uma aplicação? Basicamente são registros detalhados e estruturados dos eventos ocorridos em sua execução. Eles incluem informações sobre erros, operações...

Vantagens e Desvantagens no uso da API Date e Intl

Antes de mais nada, qual a importância de saber manipular datas na programação É importante saber manipular os objetos Date e Intl em JavaScript porque...

Entendendo biblioteca de requisições HTTP Axios

Primeiramente o que é AXIOS e sua finalidade Axios é uma biblioteca JavaScript que facilita a realização de requisições HTTP (como GET, POST, PUT, DELETE,...