admin管理员组

文章数量:1391947

I'm using a useEffect() hook in React to fetch data on an interval every five seconds. When my app first loads, the initial fetch request takes five seconds because it's in the setInterval() function.

I'm trying to make the API call on page load and then every five seconds after that, make API call on the interval to retrieve new data.

What I've tried that's not working:

useEffect(() => {
   await updateData(id, state, setState)
   .then(() => {
        const interval = setInterval(async () => {
            if (id) {
                await updateData(id, state, setState); // API call 
        }
    }, 5000);
   return () => {
      clearInterval(interval);
   };
 },[lensName, state, setState])
}

What I'm currently doing and would like to improve:

useEffect(() => {
// Make API call, once initial call is made and response is returned make calls on a 5 second interval
     const interval = setInterval(async () => {
        if (id) {
           await updateData(id, state, setState); // API call 
        }
    }, 5000);
    return () => {
            clearInterval(interval);
    };
   }, [lensName, state, setState])
}

Any help is greatly appreciated.

I'm using a useEffect() hook in React to fetch data on an interval every five seconds. When my app first loads, the initial fetch request takes five seconds because it's in the setInterval() function.

I'm trying to make the API call on page load and then every five seconds after that, make API call on the interval to retrieve new data.

What I've tried that's not working:

useEffect(() => {
   await updateData(id, state, setState)
   .then(() => {
        const interval = setInterval(async () => {
            if (id) {
                await updateData(id, state, setState); // API call 
        }
    }, 5000);
   return () => {
      clearInterval(interval);
   };
 },[lensName, state, setState])
}

What I'm currently doing and would like to improve:

useEffect(() => {
// Make API call, once initial call is made and response is returned make calls on a 5 second interval
     const interval = setInterval(async () => {
        if (id) {
           await updateData(id, state, setState); // API call 
        }
    }, 5000);
    return () => {
            clearInterval(interval);
    };
   }, [lensName, state, setState])
}

Any help is greatly appreciated.

Share Improve this question asked Feb 12, 2021 at 4:49 AMP_035AMP_035 2471 gold badge4 silver badges18 bronze badges 1
  • What's the use case here for making api call every 5 seconds? – timbersaw Commented Feb 12, 2021 at 5:01
Add a ment  | 

5 Answers 5

Reset to default 1

the important thing to note here is that your updateData function should return a promise to make await work then your above logic will work perfectly. It will wait until the first API call is not finished before going to the second line.

    useEffect(() => {
    await updateData(id, state, setState);
    const interval = setInterval(async () => {
      if (id) {
        await updateData(id, state, setState); // API call
      }
    }, 5000);

    
    //update function would be like:
    function updateData(id, state, setState) {
      ...
      return API.get("/url");
    }
  }, []);

You can use time value outside the useEffect hook. Increment it every 5 seconds and pass it as second argument of useEffect. Whenever this time value gets changed, UseEffect will get triggered and it will run the function inside it.

const [timeInterval, setTimeInterval] = useState(0);

setTimeout(() => {
  setTimeInterval(timeInterval + 1);
}, 5000);

useEffect(() => {
  await updateData(id, state, setState); // API call
}, [timeInterval]);

I would use two useEffect() calls: one for the 5 second poll, and one that fires only once (with an empty dependency array). Something like this:

// Make API call once
useEffect(() => {
  const live = true;
  if (id) {
     await updateData(id, state, setState, live);
  }
  return () => { live = false; }
}, []);

// Make API call on a 5 second interval
useEffect(() => {
  const live = true;
  const interval = setInterval(async () => {
    if (id) await updateData(id, state, setState, live);
  }, 5000);
  return () => {
    live = false;
    clearInterval(interval);
  }
}, [lensName, state, setState]);

Also note that you'll want some sort of flag to let your updateData() function know whether the ponent is still mounted. If it gets unmounted, you don't just want to cancel the interval, you'll also want to avoid calling setState().

You can add another useEffect without dependency to call api when page is first load. However, it's better to show the logic of updateData that we can know what you want to do.

// Call api when first load
useEffect(() => {
  await updateData(id, state, setState);
}, [])

// After, every five seconds to call api
useEffect(() => {
  const interval = setInterval(async () => {
    if (id) {
      await updateData(id, state, setState); // API call 
    }
  }, 5000);

  return () => {
    clearInterval(interval);
  };
}, [lensName, state, setState])

The following solution works fine, modify it as per your needs:

function App() {
  const [count, setCount] = useState(0);

  const myDummyApi = async () => {
    for (let i = 0; i < 10 ** 9; i++) {
      const val = i;
    }
    return { data: "some data" };
  };

  useEffect(() => {
    if (count === 0) { // condition for checking if the API call being made is initial one or not.
      myDummyApi().then((data) => {
        setCount(count + 1);
      });
    } else {
      const timer = setTimeout(() => {
        myDummyApi().then((data) => {
          setCount(count + 1);
          clearTimeout(timer);
        });
      }, 5000);
    }
  }, [count]);

  return (
    <div className="App">
      <span>{`Api Call ${count}`}</span>
    </div>
  );
}

Full code can be found here in sandbox.

Explanation:

  1. make a initial API call
  2. after the promise is resolved set the state and increase the count, then ponent renders again
  3. after that, as the count > 0 the API call will be made only after timeout of 5 secs.

本文标签: javascriptTrying to make an API call before using setInterval() in useEffect() hook in ReactStack Overflow