Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

215
Visualizações
Why my useEffect runs infinitely when promise gets rejected but only once when it gets fulfilled?

I am trying to fetch data from a mock backend created using JSON-server with the help of Axios. Now when the response status is 200 i.e., data fetched successfully the state of my success variable changes to true. The useEffect runs only once and message toast appears only once. But now when there is an error while fetching the data the useEffect runs infinitely and toast starts appearing non-stop one after another. Can someone explain to me why is this happening and how am I able to solve this issue?

Below is the code I have written.

import React, { useState, useEffect } from 'react';
import Loader from './../components/Loader';
import axios from 'axios';
import { toast } from 'react-toastify';

const PostsTD = () => {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState({
    status: false,
    message: '',
  });
  const [success, setSuccess] = useState(false);

  const getPosts = () => {
    axios
      .get('http://localhost:5050/posts')
      .then((res) => {
        setPosts(res.data);
        setLoading(false);
        if (res.status === 200) setSuccess(true);
      })
      .catch((error) => {
        setLoading(false);
        setError({ status: true, message: error.message });
      });
  };

  useEffect(() => {
    getPosts();

    if (error.status) {
      toast.error(error.message);
    }

    if (success) toast.success('Success!');
  }, [success, error]);

  if (loading) {
    return (
      <div className="px-28 text-center py-12">
        <Loader />
      </div>
    );
  }

  return (
    <div className="md:px-28 px-6">
      <h1 className="text-center font-extrabold text-gray-400 my-4 text-4xl">POSTS FETCHED USING AXIOS</h1>

      {posts && posts?.length > 0 ? (
        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3 py-2 px-3 bg-red-500">
          {posts?.map((post, idx) => {
            return (
              <div key={idx} className="p-3 bg-red-200 text-gray-900 rounded-md">
                <h2 className="font-semibold text-xl">{post.title}</h2>
                <p className="font-normal my-3">{post.body}</p>
              </div>
            );
          })}
        </div>
      ) : (
        <h1>NO posts to render</h1>
      )}
    </div>
  );
};

export default PostsTD;

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

  useEffect(() => {
    getPosts();

    if (error.status) {
      toast.error(error.message);
    }

    if (success) toast.success('Success!');
  }, [success, error]);

Since error is in the dependency array, any time the error changes, this effect will run. So the error changes, which causes you to get the posts, which causes the error to change, etc.

I would split this up into separate effects; one to kick off the load, and another to do the toasts:

useEffect(() => {
  getPosts();
}, []);

useEffect(() => {
  if (error.status) {
    toast.error(error.message);
  }

  if (success) toast.success('Success!');
}, [sucess, error]);
about 4 years ago · Juan Pablo Isaza Relatório

0

As others have mentioned before, your problem is with your useEffect triggering another getPosts call when it was only supposed to react to a change in success or error variables.

When doing API calls inside an effect, please consider these: (#1 is based on personal opinion)

  1. Preferably handle the promise inside the effect (or make 2 separate effects: 1 to make the call and 1 to react to success / error)
  2. Add a cleanup function to handle promise cancellation in case of a cleanup (https://beta.reactjs.org/learn/synchronizing-with-effects#fetching-data)

This is how I would probably structure it:

useEffect(() => {
    const controller = new AbortController();
    axios
        .get('http://localhost:5050/posts', {
            signal: controller.signal
        })
        .then((res) => {
            setPosts(res.data);
            setLoading(false);
            if (res.status === 200) setSuccess(true);
        })
        .catch((error) => {
            setLoading(false);
            setError({ status: true, message: error.message });
        });

    return () => {
        controller.abort();
    }
}, []);
about 4 years ago · Juan Pablo Isaza Relatório

0

Your useEffect has error as dependency and getPosts in its logic, so, if getPosts sets error (as it does) it creates an infinite loop.

useEffect => getPosts => setError => useEffect ...

You can resolve this by deleting the error dependency of your useEffect, if you still want to refetch data, I think you should directly call getPosts in getPosts in a setTimeout for example.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda