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.
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:
function Message({ message }) {
const [previewImage, setPreviewImage] = useState(undefined);
useEffect(() => {
let ignore = false;
setPreviewImage(undefined);
storage
.getFilePreview(Constants.BUCKET_ID, msg.mediaId)
.then((preview) => {
if(!ignore) {
setPreviewImage(preview)
}
});
return () => {
ignore = true;
}
},
[message.mediaId]
);
if (...) {
// System messages
return JSX;
}
if (...) {
// My messages
return JSX;
}
if (...) {
// Other person's messages
return JSX;
}
}
Then your initial code would look like this:
messages.map((msg) => <Message message={msg} key={msg.id} />);
You can learn more about why I suggested getting the preview asynchronously using useEfffect
here.