Sanity电商教程报错:无法解构null值product的image属性
解决TypeError: Cannot destructure property 'image' of 'product' as it is null及商品图片渲染问题
问题场景
跟随电商网站制作教程时,遇到错误:TypeError: Cannot destructure property 'image' of 'product' as it is null,无法正常渲染从Sanity数据库查询到的商品图片,相关代码如下:
import React from 'react' import { client, urlFor } from '../../lib/client'; const ProductDetails = ({ product, products }) => { const { image, name, details, price } = product; return ( <div> <div className='product-detail-container'> <div> <div className='image-container'> <img src={urlFor(image && image[0])} /> </div> </div> </div> </div> ) } export const getStaticPaths = async () => { const query = `*[_type == \"product\"] { slug { current } } `; const products = await client.fetch(query); const paths = products.map((product) => ({ params: { slug: product.slug.current } })); return { paths, fallback: 'blocking' } } export const getStaticProps = async ({ params: { slug }}) => { const query = `*[_type == \"product\" && slug.current == '${slug}'][0]`; const productsQuery = '*[_type == \"product\"]' const product = await client.fetch(query); const products = await client.fetch(productsQuery); console.log(product); return { props: { products, product } } } export default ProductDetails
错误原因
- 空值解构触发报错:
getStaticProps中按slug查询商品时,若数据库无对应slug的商品,返回的product为null,组件直接解构product属性会触发类型错误。 - 图片渲染逻辑不安全:即使
product存在,image可能为空数组或undefined,直接传递image && image[0]给urlFor仍可能引发异常。
解决方案
1. 组件内增加空值校验
在解构和渲染前先判断product是否存在,避免空值操作:
const ProductDetails = ({ product, products }) => { if (!product) { return <div>商品不存在或加载中...</div>; } const { image, name, details, price } = product; return ( <div> <div className='product-detail-container'> <div> <div className='image-container'> {/* 用可选链+兜底图增强安全性 */} <img src={image?.[0] ? urlFor(image[0]) : '/default-product.png'} alt={name} /> </div> <h2>{name}</h2> <p>{details}</p> <span>${price}</span> </div> </div> </div> ) }
2. 优化getStaticProps查询逻辑
- 修复查询字符串转义问题,使用参数化查询避免语法错误和注入风险;
- 处理查询为空的情况,返回404状态:
export const getStaticProps = async ({ params: { slug }}) => { // 参数化查询更规范安全 const query = `*[_type == "product" && slug.current == $slug][0]`; const productsQuery = '*[_type == "product"]' const product = await client.fetch(query, { slug }); const products = await client.fetch(productsQuery); // 查询不到商品时返回404 if (!product) { return { notFound: true }; } return { props: { products, product }, revalidate: 60 // 可选:设置静态内容重验证时间 } }
3. 简化getStaticPaths代码
去掉不必要的引号转义,让代码更简洁:
export const getStaticPaths = async () => { const query = `*[_type == "product"] { slug { current } }`; const products = await client.fetch(query); const paths = products.map((product) => ({ params: { slug: product.slug.current } })); return { paths, fallback: 'blocking' } }
关键说明
- 使用可选链操作符
?.替代&&,空值判断更简洁安全; - Sanity查询推荐用参数化方式,避免字符串拼接的潜在问题;
- 设置
notFound: true可让Next.js自动返回404页面,优化用户体验。
内容的提问来源于stack exchange,提问作者Saeed Abass
相关产品推荐
相关产品推荐

