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

Next.js+Sanity使用'use client'时params解构错误及解决方案咨询

问题分析与解决方案

核心结论

加'use client'后必须通过useEffect(或数据获取库如SWR/React Query)调用getProducts,不能像服务器组件那样直接在组件顶层用async/await。

错误原因

  1. 客户端组件不支持顶层async/await:Next.js中,async组件语法仅适用于服务器组件(无'use client'指令)。加了'use client'后,组件不能定义为async函数,否则会导致props传递异常,出现params未定义的错误。
  2. 客户端组件无法直接接收params作为props:服务器组件会自动从路由中获取params并传入props,但客户端组件需要通过useParams钩子来获取路由参数。

解决步骤

1. 调整组件结构,使用客户端钩子

  • 移除组件的async关键字
  • 用useParams获取路由中的product slug
  • 用useState存储产品数据和加载状态
  • 用useEffect触发数据获取

2. 修正数据渲染逻辑

你的getProducts返回的是数组(因为GROQ查询用了[]),而原代码存在渲染错误(比如products.name,应该是products[0]?.name),需要调整渲染逻辑适配数组结构。

修改后的完整代码

'use client'

import { useEffect, useState } from 'react'
import { useParams } from 'next/navigation'
import { getProducts } from '@/sanity/getProduct'
import { Product } from '@/app/components'
import { AiFillStar, AiOutlineMinus, AiOutlinePlus } from 'react-icons/ai'

const ProductPage = () => {
  const params = useParams()
  const slug = params.product
  const [products, setProducts] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchProduct = async () => {
      if (!slug) return
      const data = await getProducts(slug)
      setProducts(data)
      setLoading(false)
    }
    fetchProduct()
  }, [slug])

  if (loading) {
    return <div>Loading...</div>
  }

  // 因为查询的是单个slug的产品,取数组第一个元素
  const product = products[0]

  if (!product) {
    return <div>Product not found</div>
  }

  return (
    <>
      <div>
        <div className='flex flex-col justify-center items-center md:flex-row md:justify-around'>
          <div className='flex flex-col'>
            <div className='flex flex-col'>
              {product.images && product.images.length > 0 && (
                <img
                  src={product.images[0].url}
                  height={300}
                  width={300}
                  alt={product.images[0].alt || product.name}
                />
              )}
              <h2>{product.name}</h2>
            </div>
            <div className='flex flex-row'>
              {product.images && product.images.map((image) => (
                <img
                  key={image.url}
                  src={image.url}
                  alt={image.alt || product.name}
                  height={70}
                  width={70}
                />
              ))}
            </div>
          </div>

          <div className='flex flex-col'>
            <h2>{product.name}</h2>
            <div className='reviews'>
              <AiFillStar />
              <AiFillStar />
              <AiFillStar />
              <AiFillStar />
            </div>
            <h4>Details:</h4>
            <h3>{product.details}</h3>
            <p className='price'> ${product.price}</p>

            <div className='quantity-box border max-w-[100px] border-gray-300 rounded flex items-center'>
              <button className='minus-icon border-r-2 bg-transparent text-lg px-2 py-2'>
                <AiOutlineMinus />
              </button>

              <span className='quantity px-2'>4</span>

              <button className='plus-icon border-l-2 bg-transparent text-lg px-2 py-2'>
                <AiOutlinePlus />
              </button>
            </div>

            <div className='buttons'>
              <button type='button' className='add-to-cart'>
                Add to Cart
              </button>

              <button type='button' className='buy-now'>
                Buy Now
              </button>
            </div>
          </div>
        </div>

        <div className='maylike-products-wrapper'>
          <h2>You may also like</h2>
          <div className='flex justify-center items-center'>
            <div className=''>
              <Product />
            </div>
          </div>
        </div>
      </div>
    </>
  )
}

export default ProductPage

额外优化建议

  • 可以用SWR或React Query替代useEffect,它们自带缓存、重新验证等功能,更适合客户端数据获取
  • 给图片添加alt属性,提升可访问性
  • 增加错误处理逻辑(比如捕获getProducts的异常)

内容的提问来源于stack exchange,提问作者Antony Ponson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 07:28:07