I’m learning React and working on a small project where I fetch 10 random numbers with their corresponding interesting facts using the “Numbers API.” However, I’m running into an issue when I try to run the code. The error message I get is:
codeError: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
I’m not sure why this is happening. I think it has something to do with how I’m trying to display the fetched data, but I can’t figure out how to fix it.
Here the code I wrote:
codeconst originalArray = new Array(10).fill(0);
const mappedArray = originalArray.map((n, index) =>
Math.floor(Math.random() * 100)
);
console.log("mappedArray", mappedArray);
console.log("joined array string", mappedArray.join(","));
async function callApi(numbers) {
const fetchResponse = await fetch(`http://numbersapi.com/${numbers}/math`);
if (fetchResponse.ok) {
const data = await fetchResponse.json();
console.log("all good, here's the response", data);
} else console.log("There was a problem");
}
const Number = async () => {
const [add, setAdd] = React.useState([]); // <-- valid initial empty state
React.useEffect(() => {
callApi(mappedArray).then((values) => setAdd(values));
}, []); // <-- invoke on component mount
return (
<div className="container">
{add.map((newlist, i) => (
<div className="item" key={i}>
{newlist}
</div>
))}
</div>
);
};
export default Number;
I suspect I’m not handling the fetched data properly before trying to display it. Could someone please help me figure out what’s going wrong and how to fix this?
The error you’re encountering, “Objects are not valid as a React child,” occurs because the data returned from the fetch
call is not in the expected format for rendering. In this case, it seems that the response from the Numbers API is not being properly handled, leading to issues when trying to render it.
Issues in the Code:
- The
callApi
function fetches data but does not return it in a format that can be set in the state correctly. - The fetched data is not being properly stored in the component’s state before rendering.
- The
React.useEffect
does not handle promises correctly. - The component’s return statement is misplaced, causing the code to break.
Here’s how you can fix the code:
- Update the
callApi
function to fetch data for each number and return it properly. - Use
Promise.all
to handle multiple fetch requests in parallel. - Store the fetched results in the state and render them in the component.
Here’s the corrected code:
codeimport React from "react";
const originalArray = new Array(10).fill(0);
const mappedArray = originalArray.map(() =>
Math.floor(Math.random() * 100)
);
console.log("mappedArray", mappedArray);
console.log("joined array string", mappedArray.join(","));
async function callApi(numbers) {
// Fetch data for each number and return the results
const fetchPromises = numbers.map(async (number) => {
const fetchResponse = await fetch(`http://numbersapi.com/${number}/math`);
if (fetchResponse.ok) {
// Parse the response as text since Numbers API returns plain text
const data = await fetchResponse.text();
return data;
} else {
return "There was a problem fetching data.";
}
});
// Wait for all fetch promises to complete
return Promise.all(fetchPromises);
}
const Number = () => {
const [add, setAdd] = React.useState([]); // Valid initial empty state
React.useEffect(() => {
// Call the API and set the state with the fetched data
callApi(mappedArray).then((values) => setAdd(values));
}, []); // Invoke on component mount
return (
<div className="container">
{add.map((newlist, i) => (
<div className="item" key={i}>
{newlist}
</div>
))}
</div>
);
};
export default Number;
Explanation:
callApi
Function: The function now takes an array of numbers, fetches data for each usingmap
, and returns an array of promises.Promise.all
is used to wait for all the fetch requests to complete.- Data Fetching: Since the Numbers API returns plain text,
fetchResponse.text()
is used instead offetchResponse.json()
. This ensures the data can be rendered as a React child. - Setting State: The
useEffect
hook fetches the data once when the component mounts and updates the state with the results. - Rendering the Data: The data is rendered inside the
return
statement of the functional component. Each item from theadd
array is displayed within adiv
element.
With these changes, your component should now work as expected, fetching random number facts and displaying them.