Arasto
Arasto

Reputation: 491

useEffect spamming requests

State

const [user, setUser] = useState({});

checkIfUserIsEnabled()

 async function checkIfUserIsEnabled() {
  const res = await fetch("http://localhost:8080/users/finduserbytoken?id=" + 
    getTokenIdFromURL);
    res.json()
   .then(res => setUser(res))
   .catch(err => setErrors(err));
}

useEffect When i call my checkIfUserIsEnabled() in the useEffect below it gets rendered once and displays the false version in the return method.

    useEffect(() => {
        verifyEmail(getTokenIdFromURL);
        checkIfUserIsEnabled();
        return () => {
            /* cleanup */
        };
    }, [/* input */])`

useEffect (2th) If i do it like this instead, it keeps spamming the requests towards my API and displays true.

    useEffect(() => {
        checkIfUserIsEnabled();
      });

Return

    return (
        <div className="emailVerificationWrapper">
        {user.enabled 
            ? <h1>Thank you for registrating, {user.firstName}. Account is verified!</h1> 
            : <h1>Attempting to verify account...</h1>}
        </div>
    )




To my question(s): Why does the second useEffect spam the request? and is there a way i can make the request being rendered every ~2-3 second instead of the spam? and could i make it stop doing the request once it actually returns true?

Upvotes: 3

Views: 3659

Answers (2)

0xAnon
0xAnon

Reputation: 897

The effect hook runs when the component mounts but also when the component updates. Because we are setting the state after every data fetch, the component updates and the effect runs again.

It fetches the data again and again. That's a bug and needs to be avoided. We only want to fetch data when the component mounts. That's why you can provide an empty array(or something which doesn't change) as second argument to the effect hook to avoid activating it on component updates(or only when that parameter changes) but only for the mounting of the component.


let URL = `http://localhost:8080/users/finduserbytoken?id=`;
async function checkIfUserIsEnabled() {
  const res = await fetch(`$(URL)` + 
    getTokenIdFromURL);
    res.json()
   .then(res => {setUser(res); return Promise.resolve()})
   .catch(err =>  {setErrors(err); return Promise.reject()});
}

 useEffect(() => {
 const abortController = new AbortController();
    const fetchData = async() => await checkIfUserIsEnabled();
    fetchData();

  return () => {
    abortController.abort();
  };
  }, [URL]);

Upvotes: 3

Prithwee Das
Prithwee Das

Reputation: 5226

useEffect(() => {
    checkIfUserIsEnabled();
}); <-- no dependency

As your useEffect doesn't have any dependency it will run on every render, so every time you change some state and your component re-renders it will send requests.

Upvotes: 1

Related Questions