Next.js 13组件内数据传递问题:SanityData无法传入Home组件
解决SanityData数据无法传入Home组件的问题
问题核心
你遇到的问题本质是SanityData应该是异步数据获取函数,直接调用它只会返回Promise对象而非实际数据,所以外部打印会显示undefined,只有函数内部能拿到异步返回的结果。
具体解决步骤
1. 修正SanityData的返回逻辑
先确保SanityData能正确返回获取到的数据,而不是只在内部打印:
// 调整后的SanityData函数 const SanityData = async () => { try { // 这里替换成你调用Sanity API的实际逻辑 const products = await getSanityProducts(); const bannerData = await getSanityBanner(); // 必须返回数据,供外部接收 return { products, bannerData }; } catch (err) { console.error('Sanity数据获取失败:', err); // 兜底返回空数据,避免组件报错 return { products: [], bannerData: null }; } };
2. 在Home组件中异步获取并使用数据
React函数组件不能直接作为异步函数,所以要借助useEffect配合async/await来处理:
import { useEffect, useState } from 'react'; const Home = () => { // 用state存储异步获取的数据 const [products, setProducts] = useState([]); const [bannerData, setBannerData] = useState(null); useEffect(() => { // 定义内部异步函数 const loadData = async () => { // 等待SanityData返回结果 const data = await SanityData(); // 更新state setProducts(data.products); setBannerData(data.bannerData); // 此时就能正常打印数据 console.log(data.products, data.bannerData); }; loadData(); }, []); // 空依赖数组确保只在组件挂载时执行一次 // 后续可以直接用products和bannerData渲染内容 return ( <div className="home-container"> {/* 渲染banner和产品列表 */} </div> ); };
3. 避开常见误区
- 不要在组件顶层或渲染逻辑里直接调用
SanityData():异步函数返回的是Promise,不是直接数据,还会导致组件重复渲染时反复发起请求。 - 如果
SanityData是自定义Hook,要遵循React Hook规则,直接在组件内调用即可,无需额外处理异步:
// 自定义Hook版本示例 const useSanityData = () => { const [products, setProducts] = useState([]); const [bannerData, setBannerData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { const data = await SanityData(); setProducts(data.products); setBannerData(data.bannerData); setLoading(false); }; fetchData(); }, []); return { products, bannerData, loading }; }; // Home组件中使用Hook const Home = () => { const { products, bannerData, loading } = useSanityData(); useEffect(() => { if (!loading) { console.log(products, bannerData); } }, [loading, products, bannerData]); if (loading) return <div>加载中...</div>; return <div>{/* 渲染内容 */}</div>; };
内容的提问来源于stack exchange,提问作者Dukatela
相关产品推荐
相关产品推荐

