Getting an Error Objects are not valid as a React child

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:

  1. The callApi function fetches data but does not return it in a format that can be set in the state correctly.
  2. The fetched data is not being properly stored in the component’s state before rendering.
  3. The React.useEffect does not handle promises correctly.
  4. The component’s return statement is misplaced, causing the code to break.

Here’s how you can fix the code:

  1. Update the callApi function to fetch data for each number and return it properly.
  2. Use Promise.all to handle multiple fetch requests in parallel.
  3. 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:

  1. callApi Function: The function now takes an array of numbers, fetches data for each using map, and returns an array of promises. Promise.all is used to wait for all the fetch requests to complete.
  2. Data Fetching: Since the Numbers API returns plain text, fetchResponse.text() is used instead of fetchResponse.json(). This ensures the data can be rendered as a React child.
  3. Setting State: The useEffect hook fetches the data once when the component mounts and updates the state with the results.
  4. Rendering the Data: The data is rendered inside the return statement of the functional component. Each item from the add array is displayed within a div element.

With these changes, your component should now work as expected, fetching random number facts and displaying them.

Related blog posts