Error: expected ']' following expression in sanity with nextjs

196 Views Asked by At

i am trying to fetch data from sanity in nextjs but i keep getting this error Error: expected ']' following expression. I'm a novice in this, been on it, i don't even know the source of the error

these are my schemas for product.ts

import {defineField, defineType} from 'sanity'

export default defineType({
  name: 'product',
  title: 'product',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    }),
    defineField({
      name: 'price',
      title: 'Price',
      type: 'number',
    }),
    defineField({
      name: 'oldprice',
      title: 'Old Price',
      type: 'number',
    }),
    defineField({
      name: 'mainImage',
      title: 'Main image',
      type: 'image',
      options: {
        hotspot: true,
      },
      fields: [
        {
          name: 'alt',
          type: 'string',
          title: 'Alternative Text',
        }
      ]
    }),
    defineField({
      name: 'categories',
      title: 'Categories',
      type: 'array',
      of: [{type: 'reference', to: {type: 'category'}}],
    }),
    defineField({
      name: 'stock',
      title: 'Out Of Stock',
      type: 'boolean',
    }),
    defineField({
      name: 'display',
      title: 'Display',
      type: 'boolean',
    }),
    defineField({
      name: 'created',
      title: 'Created when',
      type: 'datetime',
    }),
    defineField({
      name: 'body',
      title: 'Body',
      type: 'blockContent',
    }),
  ],

  preview: {
    select: {
      title: 'title',
      author: 'author.name',
      media: 'mainImage',
    },
    prepare(selection) {
      const {author} = selection
      return {...selection, subtitle: author && `by ${author}`}
    },
  },
})

category.ts

import {defineField, defineType} from 'sanity'

export default defineType({
  name: 'category',
  title: 'Category',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    }),
    defineField({
      name: 'mainImage',
      title: 'Main image',
      type: 'image',
      options: {
        hotspot: true,
      },
      fields: [
        {
          name: 'alt',
          type: 'string',
          title: 'Alternative Text',
        }
      ]
    }),
    defineField({
      name: 'description',
      title: 'Description',
      type: 'text',
    }),
  ],
})

i used client and groq here

import { createClient, groq } from 'next-sanity'

import { apiVersion, dataset, projectId, useCdn } from '../env'


export async function getProducts(){
  
  const client = createClient({
    apiVersion,
    dataset,
    projectId,
    useCdn,
  })


  return client.fetch(

      groq`*[_type = "product"]{
          _id,
          name,
          "slug":slug.current,
          "mainImage": image.asset->url,
          price,
          oldprice,
          category->{
            name,
            "id": _id,
            "mainImage": image.asset->url
          },
          stock,
          display,
          created,
          body,
      }`
  )


}
export async function getCategory(){
  
  const client = createClient({
    apiVersion,
    dataset,
    projectId,
    useCdn,
  })


  return client.fetch(

    groq`*[_type = "category"]{
      _id,
      name,
      "slug":slug.current,
      "mainImage": image.asset->url,
      description,
    }`,
  )


}

this is my product page

export default async function Product () {

    const cats = await getCategory()
  return (
    <><div className='ml-6 pl-6'>
          <p className='font-normal leading-9 text-4xl font-sans ml-6 pl-6 pt-2 pb-6 mb-6'>Product</p>
      </div><main className='mx-6 px-6 py-6 my-6'>
              <div className="grid grid-cols-4 place-content-center ml-6 pl-6">
                    {cats.map((item: { _id: React.Key | null | undefined; mainImage: string | StaticImport; name: string | number | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | React.PromiseLikeOfReactNode | null | undefined }) => (
                        <div className="w-10/12 bg-white" key={item._id}>
                            <a href="#">
                                <Image width={300} height={300} id='image' className="w-screen md:h-fit" src={item.mainImage} alt="product image" />
                            </a>
                            <div className="px-5 pb-5 py-3 text-center">
                                <Link href="#">
                                    <h5 className="text-base font-sans leading-6 font-bold text-black">{item.name}</h5>
                                </Link>
                                <div className="mb-5">
                                    <span className="text-xs font-semibold text-[#3a3a3a] leading-6 text-center">5 PRODUCTS</span>
                                </div>
                            </div>
                        </div>

                    ))}

product/[category]/page.tsx

export default async function Product () {

    const products: IItem[] = await getProducts()

    return (
        <><div className='ml-6 pl-6'>
        <p className='font-normal leading-9 text-4xl font-sans ml-6 pl-6 pt-2 pb-6 mb-6'>Categories</p>
        </div>
        <main className="">
            <div className="grid grid-cols-4 place-content-center ml-6 pl-6">
                {products.map(item => (
                    <div className="w-10/12 bg-white" key={item.id}>
                        <a href="#">
                            <Image width={300} height={300} id='image' className="w-screen md:h-fit" src={item.mainImage} alt="product image" />
                        </a>
                        <div className="px-5 pb-5 py-3">
                            <Link href="#">
                                <p className="text-sm font-sans leading-6 font-normal text-[#3a3a3a]">{item.category}</p>
                            </Link>
                            <Link href="#">
                                <h5 className="text-base font-sans leading-6 font-bold text-black">{item.name}</h5>
                            </Link>
                            <div className="flex items-center mt-2.5 mb-5">
                                <span className="text-sm font-bold text-[#3a3a3a] leading-6">₦{item.price}</span>
                            </div>
                            <div className="flex items-center justify-between">
                                <a href="#" className="text-white bg-[#B1250A] hover:bg-black focus:ring-4 focus:outline-none focus:ring-black font-bold rounded-lg text-base px-5 py-2.5 text-center dark:bg-[#B1250A] dark:hover:bg-black dark:focus:ring-[#B1250A]">Add to cart</a>
                            </div>
                        </div>
                    </div>

                ))}

these are the interfaces

// Define a type for your item
export interface IItem {
  _id: number;
  name: string;
  slug: string;
  price: number;
  oldprice: number;
  mainImage: string;
  category: string[];
  stock: boolean;
  display: boolean;
  created: number;
  body: string;
};

export interface ICategory {
  _id: string;
  name: string;
  mainImage: string;
  slug: string;
  description: string;
}
  

please will glad if anyone could help me with this error. thanks

i tried checking if there are typos and corrected them still same error, looked online still couldn't find solution to it.

RESOLVED THE ISSUE

Well, i didn't really find the reason for the error but all I did was break down my codes, restructured them and voila, it worked

1

There are 1 best solutions below

0
On

I recently came across this issue and I believe your issue is also query related. Instead of an assignment, _type should be checking for equality. In your case, instead of:

*[_type = "product"] or *[_type = "category"]

It should be

*[_type == "product"] and *[_type == "category"]