[SOLVED] I'm trying to get data from api and render it to the screen but I can render only last data not all api response

Issue

App.tsx

export interface Hotel {
  id: string;
  name: string;
  address1: string;
  address2: string;
  starRating: number;
  images: string[];
  longDescription: string;
}

export interface Room {
  id: string;
  name: string;
  longDescription: string;
}

const App: React.FC = () => {
  const [hotels, setHotels] = useState<Hotel[]>([]);
  const [rooms, setRooms] = useState<Room[]>([]);

  useEffect(() => {
    const getDetails = async () => {
      const hotel = await axios.get<Hotel[]>(`${uri}`);
      console.log(hotel.data);

      const response = hotel.data.map(async (i) => {
        const data = await (await fetch(`${uri}/${i.id}`)).json();
        return data;
      });
      Promise.all(response).then((fetchedData) => {
        const roomData = fetchedData.map((i) => {
          return i.rooms;
        });
        console.log(roomData);
        setRooms(roomData);
      });
    };
    getDetails();
  }, []);

  return (
    <div>
      <GlobalStyle />
      <HotelCard hotels={hotels} rooms={rooms} />-
    </div>
  );
};

HotelCard.TSX is for only rendering hotel cards with rooms.

interface HotelListProps {
  hotels: Hotel[];
  rooms: Room[];
}

const HotelCard: React.FC<HotelListProps> = ({ hotels, rooms }) => {
  return (
    <div>
      {hotels.map((hotel) => (
        <div key={hotel.id}>
          <h1>{hotel.id}</h1>
          // more code
        </div>
      ))}
      {rooms.map((room) => (
        <div key={room.id}>
          <h1>{room.name}</h1>
          // more here...
        </div>
      ))}
    </div>
  );
};

export default HotelCard;

console.log(roomData) result is

(4) [Array(8), Array(6), Array(9), Array(11)] 0: (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] 1: (6)
[{…}, {…}, {…}, {…}, {…}, {…}] 2: (9) [{…}, {…}, {…}, {…}, {…}, {…},
{…}, {…}, {…}] 3: (11) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…},
{…}, {…}] length: 4 [[Prototype]]: Array(0)

and when I tried to render rooms state and I got only last result not full.

Solution

Two things…

  1. You aren’t calling setHotels so your hotels state will never change
  2. Assuming each hotel response has a rooms array, roomData will become an array of arrays and not the flat array your component expects

I’d also just stick with Axios (since you’ve already got it installed) instead of mixing in with fetch()

const { data: hotels } = await axios.get<Hotel[]>(uri);
const allRooms = await Promise.all(hotels.map(async ({ id }) => {
  // don't forget to provide a type for the response
  const { data: { rooms } } = await axios.get<{ rooms: Room[] }>(
    `${uri}/${encodeURIComponent(id)}`
  );

  return rooms;
}));

setHotels(hotels);
setRooms(allRooms.flat()); // flatten the array

Answered By – Phil

Answer Checked By – David Marino (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *