Code freshman
Code freshman

Reputation: 25

How to use object Promise in JSX

After receiving a Promise object from axios, I want to use it in JSX but error occurs "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."

//Request.js
import axios from 'axios';

const Request = axios.create({
    baseURL: 'https://ptx.transportdata.tw/MOTC/v2/'
});

export const ScenicSpotRequest = async () => Request.get('Tourism/ScenicSpot?$top=30&$format=JSON').then(response => response.data);

export async function getScenicSpotRequest() {
    try {
        const item = await ScenicSpotRequest();
        // console.log(item);
        return item;
    } catch (err) {
        console.error(err);
    }
}
//MainScreen.jsx
import { getScenicSpotRequest } from '../Request.js.js';

let test = getScenicSpotRequest().then(result => result[1].Name );

function MainScreen() {

  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        <InfoCard Name={test} Description="null" Picture="null" />
      </header>
    </div>
  );
}

export default MainScreen;

Upvotes: 0

Views: 1714

Answers (2)

lissettdm
lissettdm

Reputation: 13078

The error occurs because you are passing a Promise, not a jsx element. To get the jsx element you can create a custom hook to load the component returned by an async function:

Create the custom hook is not required to solve the problem you are facing, but you can reuse the same logic in other parts of your application:

const useAsyncComponent(fn) => { //--> fn should be an async function 
   const [Comp, setComp] = useState(null);
   useEffect(()=> {
     fn().then(C => setComp(C));
   });
  return Comp;
}


let test = getScenicSpotRequest().then(result => result[1].Name );

function MainScreen() {
  const Name = useAsyncComponent(()=> test)
  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        <InfoCard Name={Name} Description="null" Picture="null" />
      </header>
    </div>
  );
}

Upvotes: 2

Silviu Burcea
Silviu Burcea

Reputation: 5348

You need to use useEffect and store it as state in your component (or fetch it somewhere higher in the component hierarchy in an useEffect) and pass it as prop.

function MainScreen() {
  
  const [name, setName] = useState(null);
  
  useEffect(() => {
    getScenicSpotRequest().then(result => setName(result[1].Name));
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        <InfoCard Name={name} Description="null" Picture="null" />
      </header>
    </div>
  );
}

export default MainScreen;

Upvotes: 3

Related Questions