0

When the data is fetched from the API it returns an empty object. Here is the code below. It returns an empty object when I console.log then later brings back the object with data in it.

function App() {

  const [wdata, setWdata] = useState({})

  const API = "62f84860b69bddcd19d34120487d7375"


  useEffect(() => {
    fetch(`https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=${API}`)
    .then(response => response.json())
    .then(resp => setWdata(resp))
    .catch(error => console.log(error))
  }, [Left])
  console.log(wdata)
 


  return (
    <div className="App">
      <Left className="left" name={wdata.sys.country} temp={wdata.main.temp} description={wdata.weather[0].description} />
      <Right className="right" />
    </div>
  );
}
JustAG33K
  • 1,403
  • 3
  • 13
  • 28
  • 1
    It takes a couple of seconds to fetch data from your API, that's why your ```wdata``` is empty at first. – Dante_97 Aug 25 '22 at 18:19
  • See https://stackoverflow.com/a/72855782/994006 – Nice Books Aug 25 '22 at 18:33
  • 1
    @Dante_97 It actually doesn't matter how long it takes for the fetch to occur, the `console.log` will always be executed before any of the `.then` calls. That's just the nature of the JS event loop. @DAVIDLAPIDO You should read up on how the event loop works, so that you understand what is happening. "Asynchronous" code gets pushed onto a queue, to be executed later. Synchronous code will always be executed first. I put asynchronous in quotes because JS is single threaded, the event loop is used to emulate asynchronous code. – Chris Hamilton Aug 25 '22 at 18:35
  • @ChrisHamilton agreed you worded it perfectly. I just laid it out in layman's terms without getting into the details – Dante_97 Aug 25 '22 at 18:46

4 Answers4

0

You can display a loader at the time of fetching data from the Api.

Because data coming from the API needs some time.

cottontail
  • 10,268
  • 18
  • 50
  • 51
0

Try

function App() {

  const [wdata, setWdata] = useState(null)

  const API = "62f84860b69bddcd19d34120487d7375"

  const fetchData = async() => {
      await fetch(`https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=${API}`)
.then(response => response.json())
.then(resp => setWdata(resp))
.catch(error => console.log(error))
 }

  useEffect(() => {
    fetchData()
  }, [Left])
  console.log(wdata)
 


  return (
    <div className="App">
{wdata ? <Left className="left" name={wdata.sys.country} temp={wdata.main.temp} description={wdata.weather[0].description} /> : <Left className="left" name={"loading..."} temp={"loading..."} description={"loading..."} /> }
      
      <Right className="right" />
    </div>
  );
}

Apparently using async, await waits for the API to return the response and stores in your state. Before the response is received, your data will be displaying loading...

Saviee
  • 3
  • 3
0

As I said in my comment, the console.log() will always be executed before the .then() calls. This is how the JS event loop works. If you want to execute code after setWdata(resp) then simply put that code inside the .then() call.

useEffect(() => {
  fetch(`https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=${API}`)
    .then(response => response.json())
    .then(resp => { 
      setWdata(resp);
      doStuffAfter(); // Executes after setWdata
    })
    .catch(error => console.log(error))
}, [Left]);

doStuffBefore(); // Executes before all then() calls
Chris Hamilton
  • 9,252
  • 1
  • 9
  • 26
0

Can you please try this once?

function App() {

  const [wdata, setWdata] = useState({})
  const [isLoading, setIsLoading] = useState(false);

  const API = "62f84860b69bddcd19d34120487d7375"


  useEffect(() => {
    setIsLoading(true);
    fetch(`https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=${API}`)
    .then(response => response.json())
    .then(resp => setWdata(resp))
    .catch(error => console.log(error))
     setIsLoading(false);
  }, [])
  console.log(wdata)
 
  if(isLoading){
     return <loader/>;
  }

  return (
    <div className="App">
      <Left className="left" name={wdata.sys.country} temp={wdata.main.temp} description={wdata.weather[0].description} />
      <Right className="right" />
    </div>
  );
}
Drashti Kheni
  • 1,065
  • 9
  • 23