在React组件for循环中使用async/await报错,如何解决?
解决React组件中"Objects are not valid as a React child (found: [object Promise])"错误
问题原因
- 你将组件定义为
async function,React组件不能是异步函数——异步函数返回的是Promise,而React无法把Promise作为子元素渲染。 - 在组件渲染阶段直接执行
await fetchIPFSJSON,会阻塞渲染流程,同时生成Promise对象触发错误。 - 初始状态下
data为undefined,直接执行for (const a in data)会引发额外运行时问题。
修正后的代码
import { useState, useEffect } from 'react'; // 请确保已导入Card、StackGrid等所需组件 export default function DetailsViewer() { const [data, setData] = useState(null); const [processedMetadata, setProcessedMetadata] = useState([]); const [loading, setLoading] = useState(true); // 从后端获取NFT基础数据 useEffect(() => { const getNFTDetails = async () => { try { const response = await fetch("http://localhost:4000/getDetails"); const posts = await response.json(); setData(posts); } catch (err) { console.error('获取NFT详情失败:', err); } finally { setLoading(false); } }; getNFTDetails(); }, []); // 批量获取并处理IPFS元数据 useEffect(() => { if (!data) return; const fetchMetadata = async () => { const metadataList = []; for (const item of data) { const meta = await fetchIPFSJSON(item.uri); if (meta.image) { meta.image = makeGatewayURL(meta.image); } // 合并原数据与处理后的元数据,方便渲染 metadataList.push({ ...item, ...meta }); } setProcessedMetadata(metadataList); }; fetchMetadata(); }, [data]); // 处理加载状态 if (loading) { return <div>加载中...</div>; } // 处理空数据状态 if (!processedMetadata.length) { return <div>暂无数据</div>; } return ( <div style={{ maxWidth: 820, margin: "auto", marginTop: 32, paddingBottom: 256 }}> <StackGrid columnWidth={200} gutterWidth={16} gutterHeight={16}> {processedMetadata.map(item => ( <Card style={{ width: 200 }} key={item.name} title={ <div> {item.name}{" "} <a target="_blank" rel="noreferrer" href={/* 可补充跳转链接,比如NFT的详情地址 */} > {/* <LinkOutlined /> */} </a> </div> } > <img src={item.image} style={{ maxWidth: 130 }} alt={item.name} /> </Card> ))} </StackGrid> </div> ); }
关键修改说明
- 移除组件的
async关键字,确保组件返回合法的JSX元素。 - 拆分异步逻辑:用两个
useEffect分别处理后端数据获取、IPFS元数据批量请求,避免渲染阶段阻塞。 - 新增
loading状态优化加载体验,避免data未就绪时的报错。 - 用
map替代for...in循环,更符合React数组渲染的规范,同时避免遍历对象原型链的问题。 - 合并原数据与处理后的元数据,让渲染时的数据源更清晰。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

