I am new to React JS and still struggling in mastering a few concepts.
I am trying to do error handling for my code and only display the API response only after the Fetch is complete.
Below I have my code which is what I have done.
import React, { useState, useEffect } from "react";
function Transaction({ response }) {
const [transaction, setTransaction] = useState([]);
const token = "2c506c6b-d880-36bb-bdba-a035d1464b35";
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
};
useEffect(() => {
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/transaction/5KISDW53",
requestOptions
)
.then((response) => response.json())
.then((data) => setTransaction(data));
}, []);
// console.log(transaction.result.details[0].vouchers[0].result);
return (
<>
<div>
Hello
<b>Transaction Status:</b> {transaction.status} <br />
</div>
</>
);
}
export default Transaction;
And below is how I am trying to do some clean error handling. Can someone help me, or at least refer me to where I can learn how to do this properly.
import React, { useState, useEffect } from "react";
function Transaction({ response }) {
const [transaction, setTransaction] = useState([]);
const token = "2c506c6b-d880-36bb-bdba-a035d1464b35";
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
};
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
useEffect(() => {
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/transaction/5KISDW53",
requestOptions
)
.then(handleErrors)
.then((response) => console.log("ok"))
.catch((error) => console.log(error))
.then((response) => response.json())
.then((data) => setTransaction(data));
}, []);
// console.log(transaction.result.details[0].vouchers[0].result);
return (
<>
<div>
<b>Transaction Status:</b> {transaction.status} <br />
</div>
</>
);
}
export default Transaction;
CodePudding user response:
An issue I see is that you are implicitly returning the void result of a console log in the Promise chain, so later thenables aren't receiving the unpacked JSON response value.
useEffect(() => {
fetch(
"......",
requestOptions
)
.then(handleErrors)
.then((response) => console.log("ok")) // <-- returns undefined!
.catch((error) => console.log(error))
.then((response) => response.json()) // <-- can't call `json()` of undefined!
.then((data) => setTransaction(data));
}, []);
It seems like you are asking about the fetch processing. I would suggest checking for the ok response before returning the json
, right there inline. If you want to conditionally wait to display any fetched content then use a loading state.
Example:
function Transaction({ response }) {
const [loading, setLoading] = useState(true);
const [transaction, setTransaction] = useState();
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
};
useEffect(() => {
setLoading(true);
fetch(
".....",
requestOptions
)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then((data) => {
setTransaction(data)
})
.catch((error) => {
console.log(error)
})
.finally(() => {
setLoading(false);
});
}, []);
if (loading) {
return null; // or loading spinner/etc
}
return (
<>
{transaction
? (
<div>
<b>Transaction Status:</b> {transaction.status} <br />
</div>
)
: <div>No transaction data</div>
}
</>
);
}
If you want to display any errors then add some error state and some conditional rendering logic to display it, similar to the transaction state
.
CodePudding user response:
You need to keep multiple states here.
data
: For the data from APIisLoading
: For Loading StateisError
: For Error State
State:
const [transactions, setTransactions] = useState({
data: [],
isLoading: false,
isError: false,
});
and in your useEffect you should do
useEffect(() => {
setTransactions({ ...transactions, isLoading: true });
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/transaction/5KISDW53",
requestOptions
)
.then(handleErrors)
.then((response) => console.log("ok"))
.catch((error) => {
setTransactions({ ...transactions, isError: true });
})
.then((response) => {
setTransactions({
...transactions,
data: response.json(),
isLoading: false,
});
})
.then((data) => setTransaction(data));
}, []);
Then you can have conditional rendering and show the loading bar and the data elements when it's ready
CodePudding user response:
you can use conditional rendering in react.
return (
{
transaction.length === 0 ? <></> :
<>
<div>
<b>Transaction Status:</b> {transaction.status} <br />
</div>
</>
}
)
you can use loading or anything that you want instead of <></>
and also any other proper condition for data existence.