简体   繁体   中英

How use setTimeout() for a loading state in React using hooks?

I have an app that fetches data from an api. Whilst fetching there is a loading state that displays an icon to the screen. However this is a quick flash. I would like to display the loading icon on screen for a 2 seconds to improve UI and let the user know something is happening.

Here is my code:

 const [info, setInfo] = useState({});
 const [loading, setLoading] = useState(false);

useEffect(() => {
    setLoading(true);
    axios
      .get(`https://restcountries.eu/rest/v2/alpha/${code}`)
      .then((response) => {
        console.log(response);
        setInfo(response.data);
        setLoading(false);
      });

  }, []);

 return (
    <div>
      <Link to='/'>
        <button>Back</button>
      </Link>
      {loading ? (
        <LoadingIcon />
      ) : (
        <CountryInfo
          info={info}
          borders={borders}
          languages={languages}
          currencies={currencies}
        />
      )}
    </div>
  );
};

you can use promise.all

So even if your request comes early your loading will be shown for at least 2 seconds.

setLoading(true);
const fetchPromise = axios
  .get(`https://restcountries.eu/rest/v2/alpha/${code}`);
const timeOutPromise = new Promise(resolve => {
  setTimeout(resolve, 2000);
})

Promise.all([fetchPromise, timeOutPromise]).then(([response]) => {
  console.log(response);
  setInfo(response.data);
  setLoading(false);
})

api call is async as soon as the data loads the loading us set to false so you only see it for a second.

Alternatively you can also do this.

{Object.entries(info).length === 0 && info.constructor === Object ? (
        <LoadingIcon />
      ) : (
        <CountryInfo
          info={info}
          borders={borders}
          languages={languages}
          currencies={currencies}
        />

Just add setTimeout(()=>setLoading(false),2000) in the axios callback. Note this will add an additional 2 seconds to the load time, so be sure to adjust accordingly.

  useEffect(() => {
    setLoading(true);

    const request = axios
      .get(`https://restcountries.eu/rest/v2/alpha/${code}`);

    const timer = new Promise(resolve => setTimeout(resolve, 2000));

    return Promise.all([request, timer]).then(([response]) => {
      console.log(response);
      setInfo(response.data);
      setLoading(false);
    });    
  }, []);

add setTimeout in success callback.

useEffect(() => {
    setLoading(true);
    axios
      .get(`https://restcountries.eu/rest/v2/alpha/${code}`)
      .then((response) => {
        console.log(response);
        setTimeout(function(){
            setInfo(response.data);
            setLoading(false);
        },2000)
      });

  }, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM