React组件中如何访问异步GraphQL调用返回的Promise数据?
解决异步GraphQL调用的Promise数据访问问题
问题根源
getModel是异步函数,调用它会直接返回Promise对象,而非你需要的实际数据。所以你直接赋值的technique是Promise,自然无法通过.Description或.Name访问到数据。
解决方案步骤
1. 用React状态管理处理异步逻辑
在组件中通过useState存储数据,useEffect执行异步请求,同时处理加载、错误状态:
import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; export async function getModel(id) { // 把id作为参数传入,避免在组件外调用useRouter(Next.js限制) if (!id) { throw new Error("模型ID不能为空"); } try { const res = await API.graphql({ query: queries.getYawaraModel, variables: { id } }); // 根据你的截图,实际数据在res.data.getYawaraModel下,直接返回该数据 return res.data.getYawaraModel; } catch (e) { console.error("获取模型失败:", e); throw e; // 抛出错误让组件捕获处理 } } export default function Detail() { const router = useRouter(); const { id } = router.query; const [technique, setTechnique] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { if (!id) return; // Next.js路由参数初始可能为空,等待id加载完成 try { const data = await getModel(id); setTechnique(data); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchData(); }, [id]); // 依赖id,id变化时重新请求数据 // 处理不同状态的UI展示 if (loading) return <div>加载中...</div>; if (error) return <div>加载失败:{error.message}</div>; if (!technique) return <div>未找到对应模型</div>; return ( <TechniqueListCard Description={technique.Description} Technique={technique.Name} /> ); }
2. 关键细节说明
- 路由参数延迟问题:Next.js中
router.query在页面初始加载时可能为空,必须判断id存在后再发起请求。 - GraphQL数据结构:返回结果嵌套在
res.data下,需要根据你的查询名称(如getYawaraModel)提取最终数据。 - 异步函数错误处理:在
getModel中抛出错误,让组件统一处理错误状态,避免静默失败。
简化方案:用数据获取库
如果项目频繁处理异步数据,可以用SWR或React Query这类库自动处理缓存、加载、错误:
以SWR为例:
import useSWR from 'swr'; import { useRouter } from 'next/router'; // 封装请求逻辑 const fetcher = async (id) => { const res = await API.graphql({ query: queries.getYawaraModel, variables: { id } }); return res.data.getYawaraModel; }; export default function Detail() { const router = useRouter(); const { id } = router.query; // 只有id存在时才发起请求 const { data: technique, error, isLoading } = useSWR(id ? id : null, fetcher); if (isLoading) return <div>加载中...</div>; if (error) return <div>加载失败:{error.message}</div>; if (!technique) return <div>未找到对应模型</div>; return ( <TechniqueListCard Description={technique.Description} Technique={technique.Name} /> ); }
内容的提问来源于stack exchange,提问作者Tennis Smith
相关产品推荐
相关产品推荐

