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

如何在React应用中正确展示Sanity中的图片?

解决Sanity图片在React中无法显示的问题

问题描述

我是React和Sanity的新手,已搭建Sanity应用并为testimonial类型上传了图片及其他字段。目前在React应用中,除图片外其他字段均可正常显示,但使用{testimonial.image}无法识别图片路径。

相关代码

Testimonial组件代码

import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/css'
const Testimonial = ({ testimonials }) => {

    return <Swiper
        spaceBetween={20}
        slidesPerView={3}
        slidesPerGroup={4}
        className="grid max-w-screen-lg grid-cols-3 gap-x-10 gap-y-20 mt-5  select-none cursor-grab md:flex rounded-xl p-8 md:p-0 dark:bg-slate-800"
    >
        {
            testimonials.map(testimonial => <SwiperSlide
                className="border rounded-lg p-5 m:10 bg-slate-50 text-blues "
            >
                <h3 > {testimonial.rating}</h3>
                <h3 className='pt-6 md:p-8 text-center md:text-left space-y-4'> {testimonial.message} </h3>
                <img className="w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto "
                    src={testimonial.image}     
                    />
                <h3 className='text-slate-900 font-bold'> {testimonial.name} </h3>
                <h3 className='text-slate-700 dark:text-slate-500' > {testimonial.job} </h3>

            </SwiperSlide>)
        }
    </Swiper>

}

export default Testimonial

Home页面代码

import Customers from "../components/index/Customers"
import React from 'react'


const Home = ({ testimonials, members }) => {
  return (
    <div>
      <Hero />
      <Services />
      <AboutUs />
      <ChooseUs />
      <TrustUs />
      <Statics />
      <Testimonial testimonials={testimonials} />
      <Members members={members} />
      <Blogs />
      <Collaboration />
      <Customers />

    </div>
  )
}
export default Home

export async function getServerSideProps(context) {
  const projectId = 'q8l0xi0c'
  const dataset = 'production'

  let query = encodeURIComponent('*[_type == "testimonial"]')
  let url = `https://${projectId}.api.sanity.io/v2021-10-21/data/query/${dataset}?query=${query}`
  let response = await fetch(url)
  let testimonialsData = await response.json()
  console.log(testimonialsData)

  query = encodeURIComponent('*[_type == "members"]')
  url = `https://${projectId}.api.sanity.io/v2021-10-21/data/query/${dataset}?query=${query}`
  let response1 = await fetch(url)
  let membersData = await response1.json()

  return {
    props: {
      testimonials: testimonialsData.result,
      members: membersData.result
    },
  }
}

原因分析

Sanity返回的图片字段不是直接的URL字符串,而是包含图片元数据的对象,直接使用testimonial.image会导致src属性拿到的是对象而非有效URL。查看console.log(testimonialsData)的输出,会看到image字段结构类似:

{
  _type: 'image',
  asset: {
    _ref: 'image-abc123-def456-jpg',
    _type: 'reference'
  }
}

解决方法

方法1:手动构造图片URL

利用Sanity的CDN规则,从图片对象的asset._ref字段提取信息构造URL:

在Testimonial组件中添加工具函数:

const getSanityImageUrl = (image, width = 400) => {
  // 空值判断避免报错
  if (!image?.asset?._ref) return '';
  // 解析_ref字段获取图片ID和格式
  const refParts = image.asset._ref.split('-');
  const [assetId, format] = refParts[refParts.length - 1].split('.');
  // 构造CDN URL
  return `https://cdn.sanity.io/images/q8l0xi0c/production/${assetId}-${width}x.${format}`;
}

修改img标签的src属性:

<img 
  className="w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto "
  src={getSanityImageUrl(testimonial.image)}
  alt={testimonial.name} // 添加alt属性提升可访问性
/>

方法2:使用官方@sanity/image-url库(推荐)

这个库支持图片裁剪、格式转换、质量调整等功能,更灵活可靠:

  1. 安装依赖:
npm install @sanity/image-url
# 或使用yarn
yarn add @sanity/image-url
  1. 创建图片处理工具(比如src/utils/sanityImage.js):
import createImageUrlBuilder from '@sanity/image-url';

// 填入你的Sanity项目ID和数据集名称
const projectId = 'q8l0xi0c';
const dataset = 'production';

const imageBuilder = createImageUrlBuilder({ projectId, dataset });

// 导出工具函数,用于生成图片URL
export const urlFor = (source) => {
  return imageBuilder.image(source).auto('format').fit('max');
};
  1. 在Testimonial组件中导入并使用:
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/css'
import { urlFor } from '../utils/sanityImage'; // 根据你的文件路径调整

const Testimonial = ({ testimonials }) => {
    return <Swiper
        // 保持原有配置
    >
        {
            testimonials.map(testimonial => <SwiperSlide
                // 保持原有类名
            >
                // 其他字段渲染
                <img 
                    className="w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto "
                    src={testimonial.image ? urlFor(testimonial.image).width(400).url() : ''}
                    alt={testimonial.name}
                />
                // 其他字段渲染
            </SwiperSlide>)
        }
    </Swiper>
}

export default Testimonial

额外提示

  • 始终添加空值判断:如果某些testimonial没有上传图片,testimonial.image会是undefined,直接使用会导致报错
  • 可以调整width参数控制图片尺寸,适配UI需求
  • 查看console.log(testimonialsData)的输出,确认image字段结构是否符合预期

内容的提问来源于stack exchange,提问作者samira rahimi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:40:15