I am a student and we just started looking at APIs, using the https://openweathermap.org API I tried to get the forecast for Stockholm, Sweden. Didn't get very far because for some reason, I sent alot of requests, which blocked me from sending more. And don't really know what is causing it.
Would really appreciate feedback/ explanation to what I am doing wrong and can improve. Thanks in advance!
This is all I have done so far, and placed <InitialContainer>
inside function App()
import {useState} from 'react';
const InitialForecast = () =>{
const[initial, setInital] = useState();
let url = "https://api.openweathermap.org/data/2.5/weather?q=Stockholm&appid=MyID";
fetch(url).then(res => res.json()).then(data =>{
setInital(data);
// console.log(data.name);
})
return(<>
<h2>{initial.name}</h2>
</>)
}
export default InitialForecast;
CodePudding user response:
When the component renders the first time, you fetch the data and use setInitial(data)
which causes a re-render of the component. As the component gets re-rendered, you fetch the API again, and use setInitial(data)
again, and so forth.
What you need to do to get the data just once when the component is first rendered is put the fetch statement inside a useEffect
hook with no dependencies, like
const [initial, setInital] = useState();
useEffect(() => {
let url = "https://api.openweathermap.org/data/2.5/weather?q=Stockholm&appid=MyID";
fetch(url).then(res => res.json()).then(data =>{
setInital(data);
})
}, [])
...
CodePudding user response:
Your problem with your code is that your component re-renders as soon as it updates the data
variable. Try putting the request into the useEffect()
-Hook.
The useEffect-Hook runs after the component is done rendering. Any state changes won't re-render the dom again -> no fetch-loop.
You can read more about how useEffect works in the react docs.
For Ctrl C / Ctrl V action you can use this snippet:
import {useState, useEffect} from 'react';
const InitialForecast = () =>{
const[initial, setInital] = useState();
let url = "https://api.openweathermap.org/data/2.5/weather?q=Stockholm&appid=MyID";
useEffect(()=>
fetch(url).then(res => res.json()).then(data =>{
setInital(data);
}), [])
return(<>
<h2>{initial.name}</h2>
</>)
}
export default InitialForecast;
```
CodePudding user response:
What you are doing is completely wrong. You cant call APIs and setState hooks directly inside react component this will create infinite loops,
On your first API success it will set setInital(data);
and this will render the component again and it will call your API again
Solution
import {useState, useEffect} from 'react';
const InitialForecast = () =>{
const[initial, setInital] = useState();
const getIntialData = () => {
let url = "https://api.openweathermap.org/data/2.5/weather?q=Stockholm&appid=MyID";
fetch(url).then(res => res.json()).then(data => {
setInital(data);
})
}
useEffect(()=> {
getIntialData()
}, [])
return(<>
<h2>{initial.name}</h2>
</>)
}
export default InitialForecast;
The useEffect with empty array in second argument will only call at the first render of component similar to componentWillMount