skip to Main Content

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

Answers


  1. 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.

    Login or Signup to reply.
  2. 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!");
        }
      );
    }, []);
    
    Login or Signup to reply.
  3. 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!");
        }
      );
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search