如何从SanityClient的图片数组获取首张图片?排查语法报错
问题:Sanity GROQ查询语法错误及图片展示异常
我有多个set集合,希望在网页中展示每个set的首张图片作为对应画廊的跳转链接,计划获取每个set图片数组中的首张图片,但目前遇到报错:description: "expected '}' following object body"。
现有React代码
import React, { useState, useEffect } from 'react'; import { client, urlFor } from '../lib/client'; import { Header, Footer } from '../components'; import Link from 'next/link'; const gallery = () => { const [ galleryData, setGalleryData ] = useState(null); useEffect(() => { client.fetch( `*[_type == 'set']{ set_name, set_images[]->{ image{->asset{ _id, url }} } }` ).then((data) => setGalleryData(data)) .catch(err => console.error(err)) }) return ( <div> <Header /> <main className="main-gallery"> <div className="title"> <div className="title-line-left"></div> <h2>gallery</h2> <div className="title-line-right"></div> </div> <div className="categories"> <ul className="categories-container"> {galleryData && galleryData.map((set, index) => ( <li key={index}> <Link href="/sets"><img src={urlFor(set.set_images.image[0]).auto('format').url()} alt={set.set_name}/></Link> </li> ))} </ul> </div> </main> <Footer /> </div> ) }
Sanity Schema定义
export default { name: 'set', type: 'document', title: 'Set', fields: [ { name: 'set_name', type: 'string', title: 'Set Name', }, { name: 'set_images', type: 'array', title: 'Set Images', of: [ { name: 'image', type: 'image', title: 'Image', options: { hotspot: true, }, fields: [ { name: 'alt', type: 'string', title: 'Alternative Text', options: { isHighlighted: true } }, { name: 'name', type: 'string', title: 'Name', options: { isHighlighted: true } }, { name: 'date', type: 'string', title: 'Date', options: { isHighlighted: true } }, { name: 'size', type: 'string', title: 'Size', options: { isHighlighted: true } }, { name: 'materials', type: 'string', title: 'Materials', options: { isHighlighted: true } }, ] }, ] }, { name: 'slug', title: 'Slug', type: 'slug', options: { source: 'set_name' } } ] }
解决方案
1. 修复GROQ查询语法错误
报错根源是GROQ查询结构错误:根据Schema,set_images是image类型的数组,每个数组元素本身就是image对象,不需要额外嵌套image字段查询。正确的查询应该直接获取image的asset和自定义字段:
*[_type == 'set']{ set_name, slug, set_images[]{ asset->{_id, url}, alt } }
2. 修正图片路径获取逻辑
原代码中set.set_images.image[0]写法错误,set_images是数组,直接取第一个元素即可,同时要处理数组为空的边界情况避免报错。另外,跳转链接应指向对应set的详情页,用slug参数代替固定路径:
{galleryData && galleryData.map((set, index) => ( <li key={index}> {set.set_images.length > 0 && ( <Link href={`/sets/${set.slug.current}`}> <img src={urlFor(set.set_images[0]).auto('format').url()} alt={set.set_images[0].alt || set.set_name} /> </Link> )} </li> ))}
3. 完善useEffect避免无限渲染
原useEffect没有依赖数组,会导致组件无限重复执行fetch请求,添加空数组作为依赖,确保只在组件挂载时执行一次:
useEffect(() => { client.fetch( // 上面修正后的GROQ查询 ).then((data) => setGalleryData(data)) .catch(err => console.error(err)) }, []) // 添加空依赖数组
修复后的完整React代码
import React, { useState, useEffect } from 'react'; import { client, urlFor } from '../lib/client'; import { Header, Footer } from '../components'; import Link from 'next/link'; const Gallery = () => { const [galleryData, setGalleryData] = useState(null); useEffect(() => { client.fetch( `*[_type == 'set']{ set_name, slug, set_images[]{ asset->{_id, url}, alt } }` ).then((data) => setGalleryData(data)) .catch(err => console.error(err)) }, []) return ( <div> <Header /> <main className="main-gallery"> <div className="title"> <div className="title-line-left"></div> <h2>gallery</h2> <div className="title-line-right"></div> </div> <div className="categories"> <ul className="categories-container"> {galleryData && galleryData.map((set, index) => ( <li key={index}> {set.set_images.length > 0 && ( <Link href={`/sets/${set.slug.current}`}> <img src={urlFor(set.set_images[0]).auto('format').url()} alt={set.set_images[0].alt || set.set_name} /> </Link> )} </li> ))} </ul> </div> </main> <Footer /> </div> ) } export default Gallery;
内容的提问来源于stack exchange,提问作者meeppeem
相关产品推荐
相关产品推荐

