React+Next.js披萨配送应用:Sanity后端披萨图片无法渲染求助
披萨配送应用图片渲染问题及数据传递方案
我用React和Next.js开发披萨配送应用,Sanity后端的披萨图片无法渲染。已成功连接后端,终端和控制台能看到6个披萨的JSON数组,但这个问题卡了一天。另外想知道有没有其他方式把pizzas传到index.js的Home函数里。
报错信息
error - components\Menu.jsx (17:27) @ eval TypeError: (0 , _lib_client__WEBPACK_IMPORTED_MODULE_1__.default) is not a function 15 | {/* pizzas */} 16 | {pizzas.map((pizza, id) => { > 17 | const src = urlFor(pizza.image); | ^ 18 | console.log(pizza.image); 19 | return ( 20 | <div className={css.pizza} key={id}>
相关代码文件
Index.js
import Layout from '../components/layout'; import Hero from '../components/Hero'; import css from '../styles/Home.module.css'; import Services from '../components/Services'; import { client } from '../lib/client'; import Menu from '../components/Menu'; export default function Home({ pizzas }) { return ( <Layout> <div className={css.container}> <Head> <title>FUDO</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/Logo.png" /> </Head> {/* body */} <main> <Hero /> <Services /> <Menu pizzas={pizzas} /> </main> </div> </Layout> ); } export const getServerSideProps = async () => { const query = '*[_type == "pizza"]'; const pizzas = await client.fetch(query); console.log(pizzas); return { props: { pizzas, }, }; };
Menu.jsx
import urlFor from '../lib/client'; import Image from 'next/image'; export default function Menu({ pizzas }) { console.log(pizzas); return ( <div className={css.container}> <div className={css.heading}> <span>OUR MENU</span> <span>Menu That Always</span> <span>Make You Fall In Love</span> </div> {/* pizzas */} {pizzas.map((pizza, id) => { const src = urlFor(pizza.image); console.log(pizza.image); return ( <div className={css.pizza} key={id}> <div className={css.ImageWrapper}> <Image loader={() => src} src={src} alt="" objectFit="cover" layout="fill" /> </div> </div> ); })} </div> ); }
Client.js
import SanityClient from '@sanity/client'; import ImageUrlBuilder from '@sanity/image-url'; export const client = SanityClient({ projectId: 'exiz0rgv', dataset: 'production', apiVersion: '2022-09-01', useCdn: true, token: 'skT82oCId91vDPWOQoLVx6qVxX3mLxGYzSQeX0tsRRS2KGDFtmWXuIRxz0yyz3RyErMeUHraDpTDTLbWgjoiLcnh4GoL3CChOcNpkGFzQeywcAR73yQiqnxjBlL3Z435QgzTZJEEZJnI7O0R4RdQaCivBTKKIBV79efdtavbNvcfx9iSB2nS', }); const builder = ImageUrlBuilder(client); export const urlFor = (source) => builder.image(source);
问题解决
1. 图片渲染报错修复
报错核心原因有两个:
Menu.jsx中错误使用默认导入urlFor,但client.js里urlFor是命名导出,不是默认导出urlFor返回的是URL构建器对象,需要调用.url()才能拿到实际图片地址
修改Menu.jsx:
// 替换原有导入语句 import { urlFor } from '../lib/client'; // 在map循环中修改src获取方式 const src = urlFor(pizza.image).url();
额外注意:使用Next.js Image组件的layout="fill"时,父容器css.ImageWrapper必须设置position: relative,否则图片会布局异常。
2. 其他传递pizzas到Home函数的方式
除了当前的getServerSideProps,还有三种常用方案:
- 静态生成(SSG)
getStaticProps:适合数据不频繁更新的场景,预渲染页面提升性能export const getStaticProps = async () => { const query = '*[_type == "pizza"]'; const pizzas = await client.fetch(query); return { props: { pizzas }, revalidate: 60 // 可选,每隔60秒自动重新生成页面 }; }; - 客户端动态获取:在
Home组件内用useEffect拉取数据,适合需要实时更新的场景import { useState, useEffect } from 'react'; import { client } from '../lib/client'; export default function Home() { const [pizzas, setPizzas] = useState([]); useEffect(() => { const fetchPizzas = async () => { const query = '*[_type == "pizza"]'; const data = await client.fetch(query); setPizzas(data); }; fetchPizzas(); }, []); return ( <Layout> {/* 原有渲染逻辑,注意处理pizzas为空的加载状态 */} <main> <Hero /> <Services /> <Menu pizzas={pizzas} /> </main> </Layout> ); } - 全局Context传递:如果多个组件需要披萨数据,可创建全局Context,在顶层组件获取数据后存入Context,子组件直接取用,避免逐层props传递。
内容的提问来源于stack exchange,提问作者Kye
相关产品推荐
相关产品推荐

