Home > Mobile >  How to rate limit the fetch API in React?
How to rate limit the fetch API in React?

Time:02-05

I have a Vite.js App, React Template. In one of my components I want to fetch some data from https://wheretheiss.at/w/developer API. I am using useEffect. Now, the documentation mentions that the rate limiting is 1 request per second. And here is my code:

import { useState, useEffect } from "react";
import axios from "axios";

export default function Info() {
  const [info, setInfo] = useState({
    longitude: 0,
    latitude: 0,
    altitude: 0,
    velocity: 0,
    visibility: "",
  });

  const getCoords = async () => {
    const data = await axios({
      method: "get",
      url: "https://api.wheretheiss.at/v1/satellites/25544",
    });

    return data;
  };

  useEffect(() => {
    fetch("https://api.wheretheiss.at/v1/satellites/25544")
      .then((res) => res.json())
      .then((data) => {
        const lat = data.latitude;
        const long = data.longitude;
        const alt = data.altitude * 0.62137119;
        const vel = data.velocity * 0.62137119;
        const vis = data.visibility;

        setInfo({
          longitude: long.toFixed(4),
          latitude: lat.toFixed(4),
          altitude: alt.toFixed(4),
          velocity: vel.toFixed(2),
          visibility: vis === "daylight" ? "not visible" : "visible",
        });
      });
  }, [info]);

  return (
    <section className="info">
      <hr />
      <ul>
        <li>
          <strong>Latitude: </strong>
          <span>{info.latitude}°</span>
        </li>
        <li>
          <strong>Longitude: </strong>
          <span>{info.longitude}°</span>
        </li>
        <li>
          <strong>Altitdude: </strong>
          <span>{info.altitude} miles</span>
        </li>
        <li>
          <strong>Velocity: </strong>
          <span>{info.velocity} mph</span>
        </li>
        <li>
          <strong>Visibility: </strong>
          <span>{info.visibility}</span>
        </li>
      </ul>
    </section>
  );
}

I know that setting the info state as the dependencies array for my useEffect hook will determine React re-rendering the component in an infinite loop. My question is: How can I limit the fecthing for one time per second? I cannot set the dependecie array as [] because I want to constantly fetch data, because the latitude, longitude, etc., are changing every second. I cannot leave it like that either because the app will throw this error:

Uncaught (in promise): Object {..., message: "Request failed with status code 429"}

which means my app is making to many requests above the rate limit. When I get this error, my coordinates are not being re-rendered anymore and they remain the same.

Do you have any idea?

CodePudding user response:

You can use the 'axios-retry' npm package in your environment. It has the capabilities you need to use in your environment.

CodePudding user response:

step 1: import the react-debouncing lib npm i loadash

now use the loadash's debounce to debounce the function so the function will run only for 1sec so the request will also get limited to 1req per sec

here is the modified code:

import { useState, useEffect } from "react";
import axios from "axios";
import { debounce } from 'loadash';

export default function Info() {
  const [info, setInfo] = useState({
    longitude: 0,
    latitude: 0,
    altitude: 0,
    velocity: 0,
    visibility: "",
 });

  const getCoords = async () => {
    const data = await axios({
      method: "get",
      url: "https://api.wheretheiss.at/v1/satellites/25544",
    });

    return data;
  };

let debouncedReq = debounce(()=>{
 fetch("https://api.wheretheiss.at/v1/satellites/25544")
      .then((res) => res.json())
      .then((data) => {
        const lat = data.latitude;
        const long = data.longitude;
        const alt = data.altitude * 0.62137119;
        const vel = data.velocity * 0.62137119;
        const vis = data.visibility;

        setInfo({
          longitude: long.toFixed(4),
          latitude: lat.toFixed(4),
          altitude: alt.toFixed(4),
          velocity: vel.toFixed(2),
          visibility: vis === "daylight" ? "not visible" : "visible",
        });
      });
}, 1000) // now the function is debounced for 1000ms

  useEffect(() => {
   debouncedReq()
  }, [info]);

  return (
    <section className="info">
      <hr />
      <ul>
        <li>
          <strong>Latitude: </strong>
          <span>{info.latitude}°</span>
        </li>
        <li>
          <strong>Longitude: </strong>
          <span>{info.longitude}°</span>
        </li>
        <li>
          <strong>Altitdude: </strong>
          <span>{info.altitude} miles</span>
        </li>
        <li>
          <strong>Velocity: </strong>
          <span>{info.velocity} mph</span>
        </li>
        <li>
          <strong>Visibility: </strong>
          <span>{info.visibility}</span>
        </li>
      </ul>
    </section>
  );
}
  • Related