Reputation: 25
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
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
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