I have a React component that maps through an array of messages and returns a bunch of JSX based on a few conditions:
messages.map(async (msg) => {
let previewImage: URL | undefined = undefined;
if (msg.mediaId) {
previewImage = await storage.getFilePreview(
Constants.BUCKET_ID,
msg.mediaId
);
}
if (...) {
// System messages
return JSX;
}
if (...) {
// My messages
return JSX;
}
if (...) {
// Other person's messages
return JSX;
}
});
This used to work fine before I added the async function to get the preview image if the message contains a mediaId
. However, after making the function async
because I needed to await
the getFilePreview
call, I’m now getting this 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.
2
Answers
First take into account the comment left by @ray as it explains everything. With this in mind, I recommend you create a component that will take care of rendering a message, so you can leave the responsibility of loading the preview of your image to it without affecting your
messages.map(...)
and your code will be more readable.For example, look at this snippet:
Then your initial code would look like this:
You can learn more about why I suggested getting the preview asynchronously using
useEfffect
here.The error you’re encountering is because you’re trying to return a Promise ([object Promise]) from within the map function, but React expects synchronous values to be returned in order to render JSX.
In your code, you’re using async within the map callback function, which means that some of your return values might be Promises. React doesn’t know how to handle Promises directly as JSX content. To fix this, you need to structure your code so that you’re only returning synchronous JSX elements.
Here’s how you can achieve this: