Reputation: 13
When I use setApi(data.time);
in the fetch section I can normally do console.log(api.updated);
, but why I can not do just like what I wrote in the code below?
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [api, setApi] = useState({});
useEffect(() => {
fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
.then((res) => res.json())
.then((data) => {
setApi(data);
});
}, []);
console.log(api.time.updated);
return (
<div className="App">
<h1>Currency Exchange</h1>
{/* <p>Time: {api.time.updated}</p>
<u>
<li>Code: {api.bpi.USD.code}</li>
<li>Rate: {api.bpi.USD.rate}</li>
</u> */}
</div>
);
}
Upvotes: 1
Views: 87
Reputation: 509
you can use a extra state to check loading data and display it when fetch done:
export default function App() {
//add loading to check api request and data to save result
const [api, setApi] = useState({ loading: false, data: undefined });
useEffect(() => {
setApi({ loading: true });
fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
.then((res) => res.json())
.then((data) => {
setApi({ loading: false, data: data });
});
}, []);
return (
<>
{!api.loading && api.data ? (//check if data is loaded
<div className="App">
<h1>Currency Exchange</h1>
<p>Time: {api.data.time.updated}</p>
<u>
<li>Code: {api.data.bpi.USD.code}</li>
<li>Rate: {api.data.bpi.USD.rate}</li>
</u>
</div>
) : (
<>Loading data...</>//show a message while loading data(or <></> if want not display something)
)}
</>
);
}
Upvotes: 0
Reputation: 375
Your revised code:
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [api, setApi] = useState({});
useEffect(() => {
fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
.then((res) => res.json())
.then((data) => {
setApi(data);
});
}, []);
return (
<div className="App">
<h1>Currency Exchange</h1>
{api.time?.updated && <><p>Time: {api.time.updated}</p>
<u>
<li>Code: {api.bpi.USD.code}</li>
<li>Rate: {api.bpi.USD.rate}</li>
</u></>}
</div>
);
}
Simple way to check and ensure the API resolved with the appropriate data, then show the designated information.
Note that there's a reason why you have .then for your API query - it takes time to come back. Your code was executing before the api state could be filled with the response.
With the logical && operator, there's a simple way to look at it with React and I use it all the time.
If I have a loader component or something I want to show only when the loading variable is true, I can do something like this:
{loading && <Loader />}
The code to the right of the && will ONLY run if the left side is true. Since it's AND, if the first part is false it doesn't matter what the other parts are and they're skipped.
Upvotes: 0
Reputation: 112917
Before the request is complete api
will be an empty object. api.time
will then be undefined
, and trying to access property updated
on that will give rise to your error.
You could use the logical AND &&
operator to make sure api.time
is set.
const [api, setApi] = useState({});
useEffect(() => {
fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
.then((res) => res.json())
.then((data) => {
setApi(data);
});
}, []);
console.log(api.time && api.time.updated);
Upvotes: 1