skip to Main Content

The api response consisting of properties such as films and vehicles array of urls and by fetching those, I’m trying to get the resultant objects and trying to update it back inside those mentioned properties.

After returning the promises using Promise.all, I’m trying to set the films and vehicles with the results, but I’m unable to get the desired output. Here’s my Working Code Link

Any help regarding the problem would be appreciated.

I’m getting the below issue after setting films and vehicles in the response objects after waiting for promises to get the results:

enter image description here

Here in this case, I’m getting the films first but not with the desired output where the films needs to the array of objects, but instead getting the promise status.

enter image description here

Next, I’m getting the films result as pending and vehicles promise fulfilled result instead of the resultant array of objects in the mentioned object properties.

How to reolve this issue? My one only desired output is to get the films and vehicles array of objects inside the response object which I have kept in the newState.

Please find my code below:

import { useEffect, useState } from "react";
const url = `https://swapi.dev/api/people/`;

export function ToDo() {
  const [results, setResults] = useState([]);

  useEffect(() => {
    apiCallHandler(url);
  }, []);

  async function asyncAllPromises(arr) {
    const promises = await arr.map(async (item) => {
      const response = await fetch(item, { cache: "no-cache" });
      const json = await response.json();
      return json;
    });
    const response = await Promise.all(promises);
    return response;
  }

  const apiCallHandler = async () => {
    try {
      const response = await fetch(url);
      let data = await response.json();

      let newState = data.results.map((result) => {
        result.films = asyncAllPromises(result.films).then((data) => data);
        result.vehicles = asyncAllPromises(result.vehicles).then(
          (data) => data
        );
        return result;
      });

      setResults(newState);
    } catch (error) {
      console.error("Unable to find data", error);
    }
  };

  console.log("results", results);

  const table =
    results && results.length ? (
      <table>
        <thead>
          <tr>
            <td>Name</td>
            <td>Mass</td>
          </tr>
        </thead>
        <tbody>
          {results.map((result, index) => {
            return (
              <tr key={index}>
                <td>{result.name}</td>
                <td>{result.mass}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    ) : (
      "Loading.."
    );

  return <>{table}</>;
}

2

Answers


  1. You forgot to call await in lines 27 and 28, so result.films is kept as a Promise. In addition, the .then(data=>data) is redundant.

    Therefore, the definition of newState should be changed to:

    let newState = await Promise.all(data.results.map(async result => {
      result.films = await asyncAllPromises(result.films).then((data) => data);
      result.vehicles = await asyncAllPromises(result.vehicles);
      return result;
    }));
    

    The Promise.all() is used to convert the Promises returned by the async mapper function back into one Promise which is then awaited.

    Hope this helps!

    Login or Signup to reply.
  2. Your issue is because of how newState is calculated

    let newState = data.results.map((result) => {
      result.films = asyncAllPromises(result.films).then((data) => data);
      result.vehicles = asyncAllPromises(result.vehicles).then(
        (data) => data
      );
      return result;
    });
    

    Since asyncAllPromises is returning a Promise, you need to wait for it. Second, map will be returning a Promise. You so need to wait for it as well.

    You can fix this issue by:

    let newState = await Promise.all(data.results.map(async (result) => {
      result.films = await asyncAllPromises(result.films)
      result.vehicles = await asyncAllPromises(result.vehicles);
      return result;
    }));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search