Search code examples
javascriptreactjspromiseaxiosipfs

Returning a promise object instead during retrieval


I have a mapping and in each mapping i want to get data in the file storage IPFS such as the name. Then I want to return the name on the interface. However, I get a "Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead." Can someone please help me? been trying to solve this for hours. Can't seem to understand why because I know that hName should be a string.

{this.props.hawkers.map((hawker, key) => {
          const hawkerDetails = axios
            .get("https://ipfs.infura.io/ipfs/" + hawker.profileHash)
            .then(function (response) {
              console.log("this is the data: ", response.data);
              return response.data;
            })
            .catch(function (error) {
              console.log(error);
            });

          const hName = hawkerDetails.then((details) => {
            return hName;
          });
 return (
            <>
              <h4 style={{ display: "flex", marginTop: 20 }}>
                <Link
                  to={`/hawkerInfo/${hawker.owner}`}
                  // state={{ chosenHawkerPk: hawker.owner }}
                  state={{ chosenHawkerPk: hawker }}
                >
                  {hName}
                </Link>
              </h4>

Solution

  • There are several things going on.

    1. You're not using React state to manage your data.

    2. You're passing in detailsas an argument to your then method, and then not using it so hName is meaningless. It should probably be details.hName.

    3. Ideally you want to create an array of promises and then process the data with Promise.all. In my example I've used async/await.

    4. Once you've set your state you then need to map over your data in your return to create the HTML.

    // Initialise state
    const [ hawkers, setHawkers ] = useState([]);
    
    // Async function called by the `useEffect` method
    async function getData() {
    
      // Create a list of Axios promises
      const promises = this.props.hawkers.map(hawker => {
        const url = `https://ipfs.infura.io/ipfs/${hawker.profileHash}`;
        return axios.get(url);
      });
    
      // Wait for all the data to return
      const responses = await Promise.all(promises);
    
      // Use `map` to return a new array of each response's data
      const hawkers = data.map(response => response.data);
    
      // Set the state with that array
      setNames(hawkers);
    }
    
    // useEffect runs once if you pass in an empty
    // array dependency
    useEffect(() {
      getData();
    }, []);
    
    if (!hawkers.length) return <div>Loading</div>;
    
    // Now just `map` over the data that you put in state
    return (
      <>
        {hawkers.map(hawker => {
          <h4>
            <Link to={`/hawkerInfo/${hawker.details.owner}`}>
              {hawker.details.name}
            </Link>
          </h4>
        })};
      </>
    )