Reputation: 41
I have a two data in cardTypeData :
0: {id: 226, obj: {…}, Slug: 'hello-0'
1: {id: 228, obj: {…}, Slug: 'hello-1'}
useEffect(() => {
let newcard = [];
console.log("cardTypeData= ",cardTypeData)
if (cardTypeData) {
cardTypeData.map((item) => {
if(item.Slug){
const requestUrl = `chartconfig/${item.Slug}/${
searchQuery?.year
? `?year=${searchQuery.year}${
searchQuery.month ? "&month=" + searchQuery.month : ""
}`
: ``
}`;
axiosRequest.get(requestUrl)
.then((res) => {
newcard.push(res.data);
})
.catch(console.log('err'))
// .catch((error)=>{
// console.log(error)
// });
}
});
}
console.log('list', newcard)
setCardData(newcard);
}, [cardTypeData]);
the console output is shown in the figure,
how to fix this issues.
here data is shown but i could not display it in html.
Upvotes: 0
Views: 99
Reputation:
Refactor, refactor, and refactor again. The above solutions overall work as expected, but could be written better. I hope you do not mind if I show you how it should look like.
function loadNewCards() {
if (!cardTypeData) return
cardTypeData.forEach(async (cardItem) => {
if (!cardItem.Slug) return
const searchParams = new URLSearchParams(searchQuery).toString()
const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`
const response = await axios.get(requestUrl).catch(console.log)
if (!response) return
setCardData(prevCardData => [...prevCardData, response.data])
})
}
useEffect(() => {
loadNewCards()
}, [cardTypeData])
Firstly, please avoid nesting. It makes your code less readable. Try to use negation to avoid nested if / else statement.
if (!cardItem.Slug) return
would be better than
if (item.Slug) {
const requestUrl = `chartconfig/${item.Slug}`
Secondly, please use URLSearchParams to build the query params.
This class will handle your object that contains year
and month
.
I think it is better to have
const searchParams = new URLSearchParams(searchQuery).toString()
const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`
instead of
const requestUrl = `chartconfig/${item.Slug}/${
searchQuery?.year
? `?year=${searchQuery.year}${
searchQuery.month ? '&month=' + searchQuery.month : ''
}`
: ``
}`
Upvotes: 2
Reputation: 1661
Network request is asynhcronous. Before newcard.push(res.data)
runs, setCardData(newcard)
is already executed with initialized value of newcard which is [ ], ...you can modify the code something similar as below to make it work
useEffect(() => {
// let newcard = [];
console.log("cardTypeData= ",cardTypeData)
if (cardTypeData) {
cardTypeData.map((item) => {
if(item.Slug){
const requestUrl = `chartconfig/${item.Slug}/${
searchQuery?.year
? `?year=${searchQuery.year}${
searchQuery.month ? "&month=" + searchQuery.month : ""
}`
: ``
}`;
axiosRequest.get(requestUrl)
.then((res) => {
***** modified 👇*****
// newcard.push(res.data);
setCardData(prev => [...prev, res.data])
})
.catch(console.log('err'))
// .catch((error)=>{
// console.log(error)
// });
}
});
}
console.log('list', newcard)
// setCardData(newcard);
}, [cardTypeData]);
Upvotes: 1
Reputation: 634
I've read somewhere that console.log doesn't always run the exact time you call it, sometimes it waits a bit especially when you expand the input.
The problem might be from the api calls from the cardTypeData.map.
Try using for instead to test it out. Also you will have to extract the async part because React doesn't like async useEffect..
Something like this:
const loadNewCards = async () => {
let newcard = [];
console.log("cardTypeData= ", cardTypeData);
if (cardTypeData) {
for (let item of cardTypeData) {
if (!item.Slug) {
const requestUrl = `chartconfig/${item.Slug}/${
searchQuery?.year
? `?year=${searchQuery.year}${
searchQuery.month ? "&month=" + searchQuery.month : ""
}`
: ``
}`;
await axiosRequest
.get(requestUrl)
.then((res) => {
newcard.push(res.data);
})
.catch(console.log("err"));
}
}
}
console.log("list", newcard);
setCardData(newcard);
};
useEffect(() => {
loadNewCards();
}, [cardTypeData]);
And if you worried about performance you should use Promise.all to run all the calls in parallel.
Upvotes: 1