Search code examples
javascriptnode.jsreactjsrestnode-fetch

React Promise will not return a value


When trying to resolve my promise, I get the error "Objects are not valid as a React child (found: [object Promise])."

In the console.log after my API request in GetCardsFromBoard(), the typeOf() my response is string and it prints out the data to the console. But in TrelloTester(), the console shows that my response is still Promise<pending> and I get the error.

I've tried so many configurations but I can't get my promise to resolve, thanks for any help!

const fetch = require('node-fetch');

export async function GetCardsFromBoard(board) {
    
    let cards = await fetch(
        baseURL+'boards/'+board+'/cards?key='+key+'&token='+token, 
        {
          method: 'GET',
          headers: {
            'Accept': 'application/json'
        }
      })
      .then(response => {return response.text()})
      .catch(err => console.error(err));

      console.log(typeof(cards), cards); //prints "string" type and then the entire json response
      return cards;
}

export function TrelloTester() {


    let bodyStr = GetCardsFromBoard(boardID);
    console.log("resp: ", bodyStr); //shows Promise<pending>, but with the correct response value inside

    return (
        <BigCard header=" " body={bodyStr}/>
    );
    
}

export default TrelloTester;

Solution

  • GetCardsFromBoard returns a Promise. async/await is just sugar on top of promises and doesn't actually make the code any less asynchronous. Therefore, your TrelloTester component will still have to treat the function as a Promise.

    Note that I removed the then in your promises; if you're using async/await then you can just await all the promises!

    export async function GetCardsFromBoard(board) {
      try {
        const cards = await fetch(
            baseURL+'boards/'+board+'/cards?key='+key+'&token='+token, 
            {
              method: 'GET',
              headers: {
                'Accept': 'application/json'
            }
          })
        return await cards.text();
      } catch(e) {
        console.log(e);
      }
    }
    

    In you component, since this is asynchronous, I recommend treating it as an effect and using the useEffect hook in conjunction with the useState hook.

    import React, { useEffect, useState } from "react";
    
    export function TrelloTester() {
      const [bodyStr, setBodyStr] = useState("");
    
      useEffect(() => {
        cont getCards = async () => {
          const cards = await GetCardsFromBoard(boardID);
          setBodyStr(cards);
        }
        getCards();
      }, []);
    
      return bodyStr ? (
        <BigCard header=" " body={bodyStr}/>
      ) : "Loading...";
        
    }
    
    export default TrelloTester;