Home > database >  How to use useEffect() without performance degradation
How to use useEffect() without performance degradation

Time:10-19

I have a React Native app where, on one screen, I have a useEffect hook that constantly fetches data from a site and updates my local variable with that data (see below for a simplified example). The problem I am running into though is that this is killing the performance of my app. Even if you leave this screen, the app is sluggish.

The issue is no doubt caused by the countless calls to the URL to get the data & constantly resetting my local variable with the data. I tried using a dependency array with the hook, but if I do that it doesn't continually update, it only updates on the first load of the screen and I need it to update whenever there is a change (whenever new data is available).

Is there a way to do this so that I constantly get any updates from the remote source but don't slow down my app?

const [retrievedData, setRetrievedData] = [{}];

useEffect(() => {
    let fetchedData;

    fetch(
      'https://site-with-data.com',
    )
      .then(response => response.json())
      .then(json => {
        setRetrievedData(processData(json.events));
      })
      .catch(error => console.error(error));
});

CodePudding user response:

When useEffect doesn't have a dependencies array (the second argument), it will run on every render. That is why you are making so many calls.

If you need to update the data real-time, the first question you must answer is: how will the client know the data has changed in the server?

One way you could make the server notify the client is by using WebSockets. A WebSocket creates a bidirectional connection between the client and the server, and the server can notify the client whenever anything changes. Other than that, you could also use a technique called "long polling" or "server-sent events".

But any of these three solutions would require you to change your server (in addition to your client).

Quick fix: limit the update frequency to "refresh every N seconds"

The quick and dirty alternative without changing the server is just to decide a frequency (e.g., update every 5s) and go with it in the client.

Example:

useEffect(() => {
  const intervalId = setInterval(() => {

    fetch(
      'https://site-with-data.com',
    )
      .then(response => response.json())
      .then(json => {
        setRetrievedData(processData(json.events));
      })
      .catch(error => console.error(error));
    
  }, 5000); // update every 5s

  return () => clearInterval(intervalId);

}, []); // add to this array any variable that affects the fetch (e.g., URL)

Which number of seconds should you use? That will depend on each case. To decide that, evaluate both UX and server load.

  • Related