Home > Software design >  How to wait for all the functions and then render in React native?
How to wait for all the functions and then render in React native?

Time:09-23

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.

screen

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
  };
}
  • Related