I am getting data from API's and here is my functions
useEffect(() => {
getSeller();
getReviews();
}, []);
const getSeller = async () => {
let data = await api.get(`/${itemSeller}/`).then(({ data }) => data);
setUser({ user: data[0].first_name ' ' data[0].last_name });
};
const getReviews = async () => {
let data = await ReviewsApi.get(`/${itemId}/`).then(({ data }) => data);
data.map((a) => getReviewGiverName(a, data));
};
const getReviewGiverName = async (a, data) => {
let data1 = await api.get(`/${a.buyer}/`).then(({ data }) => data);
a.buyername = data1[0].first_name ' ' data1[0].last_name;
setReviews(data);
};
I am adding a new field buyer name to my reviews list which in which I have stored data from API. But the problem is that if I ```console.log(reviews)```` it displays correctly the buyer name in every object of reviews list but if I render these on-screen through map function.... it displays some buyer name but for some buyer name it shows empty space.
CodePudding user response:
Maybe do it like this will help
const getReviews = () => {
ReviewsApi.get(`/${itemId}/`).then(({ data }) =>
data.map((a) => getReviewGiverName(a, data))
);
};
OR
You can focus on the setReviews
state so it will re-render whenever reviews change.
useEffect(() => {
getSeller();
getReviews();
}, [reviews]);
CodePudding user response:
But the problem is that if I
console.log(reviews)
it displays correctly the buyer name in every object of reviews list but if I render these on-screen through map function.... it displays some buyer name but for some buyer name it shows empty space.
It seems you are enqueueing multiple asynchronous requests in a loop, and each one is independently updating state.
There also appears to be some object mutations going on when getReviewGiverName
is appending new buyername
property to a
which is a review object in data
.
You are also mixing async/await
syntax with Promise chains. Generally you should pick one or the other.
const getReviews = async () => {
let data = await ReviewsApi.get(`/${itemId}/`)
.then(({ data }) => data);
data.map(a => getReviewGiverName(a, data))
}
const getReviewGiverName = async (a, data) => {
let data1 = await api.get(`/${a.buyer}/`)
.then(({ data} ) => data);
a.buyername = data1[0].first_name ' ' data1[0].last_name;
setReviews(data) ;
}
To resolve I suggest mapping the getReviewGiverName
requests into an array of Promises and Promise.all
them and then update/set the reviews
state. In the getReviewGiverName
fetch the review's buyer and compose a new review object with buyername
property. Promise.all
returns an array of the mapped data
which is the new reviews
state.
const getReviews = async () => {
const { data } = await ReviewsApi.get(`/${itemId}/`);
const reviews = await Promise.all(data.map(getReviewGiverName));
setReviews(reviews)
}
const getReviewGiverName = async (review) => {
const { data } = await api.get(`/${review.buyer}/`);
return {
...review,
buyername: data[0].first_name ' ' data1[0].last_name
};
}