react shows toast multiple times

138 Views Asked by At

Currently i have started learning in React to call API but when component is rendered on browser side from below code toast message is shown two times instead of single time. Can someone please help me to fix this issue? Thanks in advance!

const [toastShown, setToastShown] = useState(false);
  useEffect(() => {
    document.title = "All Courses";

    axios.get(`${base_url}/courses`).then(
      (response) => {
        setCourses(response.data);
        if (!toastShown) {
          toast.success("Courses loaded successfully!");
          setToastShown(true);
        }
      },
      (error) => {
        toast.error("Something went wrong!");
      }
    );
  }, [toastShown]);
3

There are 3 best solutions below

1
On

In the development mode, StrictMode is enabled which runs useEffect twice. Try to build the code and test it in Production mode. If it runs twice, try to use AbortController to stop the first API call, which stops the execution of then.

0
On

It's showing twice because you're performing the operation twice. Note the useEffect dependency:

}, [toastShown]);

So this effect will run if toastShown changes. What does this effect do?:

  • Perform an AJAX operation
  • Show the Toast
  • Set toastShown to true

So the effect will run once when the component loads with the initial (false) value of toastShown, and then run again when the component re-renders with the new (true) value of toastShown.

You appear to have simply over-engineered yourself into this scenario. Remove toastShown entirely:

useEffect(() => {
  document.title = "All Courses";

  axios.get(`${base_url}/courses`).then(
    (response) => {
      setCourses(response.data);
      toast.success("Courses loaded successfully!");
    },
    (error) => {
      toast.error("Something went wrong!");
    }
  );
}, []);
0
On

When you update the toastShown state inside the useEffect, it triggers the effect again because toastShown is in the dependency array.You can remove toastShown from the dependency array if you only want the effect to run once when the component mounts.

const [toastShown, setToastShown] = useState(false);

useEffect(() => {
  document.title = "All Courses";

  axios.get(`${base_url}/courses`).then(
    (response) => {
      setCourses(response.data);
      if (!toastShown) {
        toast.success("Courses loaded successfully!");
        setToastShown(true);
      }
    },
    (error) => {
      toast.error("Something went wrong!");
    }
  );
}, []);