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>
);
}