Nextjs+Sanity弹窗图片画廊功能失效,请求排查问题
针对你遇到的点击图片无响应、控制台404/500错误,以下是具体问题点和修复步骤:
1. 404错误:Modal箭头图片路径错误
Next.js中,public目录下的资源路径不需要包含public或项目根目录前缀,直接用/images/cart.png即可。原代码里的路径/next_portfolio/public/images/cart.png会导致资源找不到,触发404。
修改Modal组件代码:
// Modal.js 里的箭头图片部分 <div onClick={handleRotationRight} className="overlay-arrows_left"> <img src="/images/cart.png" alt='切换箭头'/> </div>
2. 500错误+点击图片不识别:图片URL传递错误
你当前存到clickedImage的是Sanity的image对象(不是可直接访问的URL),Modal里直接把对象作为src值,会导致无效请求触发500。同时存在变量重名、索引逻辑冗余的问题:
2.1 修复map循环变量重名
原代码中imagesData.imageItems.map((imagesData, index)的imagesData和外层props的imagesData重名,会覆盖父级变量,导致内部访问错误。
修改sets页面的map部分:
{imagesData.imageItems && imagesData.imageItems.map((imageItem, index) => ( <li key={index}> <img src={urlFor(imageItem.image).auto('format').url()} className="the_image" alt={imageItem.alt || '画廊图片'} onClick={() => handleClick(imageItem, index)} /> </li> ))}
2.2 修复handleClick函数:存储图片URL而非对象
点击图片时,应该用urlFor生成可直接访问的URL,而不是存储Sanity的image对象。
修改sets页面的handleClick函数:
const handleClick = (imageItem, index) => { setCurrentIndex(index); // 生成图片URL并存入状态 setClickedImage(urlFor(imageItem.image).auto('format').url()); };
2.3 修复handleRotationRight函数:索引逻辑简化+正确传递URL
原函数里的filter逻辑冗余,且错误地存储了整个imageItem对象,需要简化索引计算并正确生成图片URL。
修改sets页面的handleRotationRight函数:
const handleRotationRight = () => { if (!imagesData.imageItems || currentIndex === null) return; const totalLength = imagesData.imageItems.length; // 计算新索引,自动循环 const newIndex = (currentIndex + 1) % totalLength; const newImageItem = imagesData.imageItems[newIndex]; // 生成新图片的URL setClickedImage(urlFor(newImageItem.image).auto('format').url()); setCurrentIndex(newIndex); };
3. 优化:合并Sanity查询减少请求
原getServerSideProps里的两个查询可以合并成一个,减少对Sanity的请求次数,同时确保数据结构一致。
修改getServerSideProps:
export const getServerSideProps = async (pageContext) => { const setSlug = pageContext.query.slug; const combinedQuery = `*[_type == 'set' && slug.current == $setSlug][0]{ set_name, 'imageItems':set_images[]{image{asset->{_id, url}, alt, name, date, size, materials}} }`; const data = await client.fetch(combinedQuery, {setSlug}); return { props: { setData: { set_name: data.set_name }, imagesData: { imageItems: data.imageItems } } } }
4. 额外优化:Modal的关闭逻辑增强
原Modal的关闭逻辑可能因为事件冒泡出现问题,可以直接在点击遮罩和关闭按钮时调用setClickedImage(null),无需判断class:
修改Modal组件的handleClick:
const Modal = ({clickedImage, handleRotationRight, setClickedImage}) => { const closeModal = () => setClickedImage(null); return( <> <div className="overlay" onClick={closeModal}> {/* 阻止图片区域的点击事件冒泡,避免点击图片关闭Modal */} <img src={clickedImage} alt='预览图片' onClick={(e) => e.stopPropagation()}/> <span className="dismiss" onClick={closeModal}>x</span> </div> <div onClick={handleRotationRight} className="overlay-arrows_left"> <img src="/images/cart.png" alt='切换到下一张'/> </div> </> ) };
完成以上修改后,点击图片应该能正常弹出Modal显示放大图,404/500错误也会消失,同时索引逻辑可以支持后续的幻灯片切换功能。
内容的提问来源于stack exchange,提问作者paparonnie

