You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
    },
  };
};
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:39:45