Home > other >  I`m trying to get data from api and render it to the screen but i can render only last data not all
I`m trying to get data from api and render it to the screen but i can render only last data not all

Time:03-16

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.

CodePudding user response:

According to your log, roomData is an array of arrays. You can modify your code snippet in Promise.all(...) to have roomData as array of objects:

let roomData = [];
fetchedData.forEach((i) => {
    roomData = [...roomData, ...i.rooms];
});

CodePudding user response:

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