🔮 Sanity Create is here. Writing is reinvented. Try now, no developer setup

How to set a slug for a product variant in Sanity and how to handle routes in Gatsby for product variants.

7 replies
Last updated: Jun 27, 2021
Hello, I have a schema known as
productVariant
with bunch of fields within, one of them being a
type
:
slug
. This
productVariant
document is referenced in my main
products.js
schema, allowing me to create variants of the product in Sanity studio.

products.js

    {
      title: 'Variants',
      type: 'array',
      of: [
        {
          title: 'Variant',
          type: 'productVariant',
        },
      ],
    },
My question is... I want a slug for my
productVariant
which i can eventually use to append to the end of my product slug on Gatsby. How can I do so in my
productVariant
schema if say, i want my
productVariant
slug to be
title
of the variant?

productVariant.js

export default {
  title: 'Product variant',
  name: 'productVariant',
  type: 'object',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'string',
    },
    {
      title: 'Slug',
      name: 'slug',
      type: 'slug',
    },
Jun 24, 2021, 2:26 AM
Two suggestions to start—and maybe you’ve already done this—but I would give your variants array in products.js a
name
and set
options.source
on your slug.
Your title will already be the title of each item in your variants array, so I don’t follow when you are asking about making the productVariant slug the title of the variant. Do you mean you want to set the title of your products document?
Jun 24, 2021, 3:17 AM
If that were the case, you might try something like:

// productVariant.js

export default {
  title: 'Product variant',
  name: 'productVariant',
  type: 'object',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'string',
    },
    {
      title: 'Slug',
      name: 'slug',
      type: 'slug',
      options: {
        source: (_, {parent}) => {
          return parent.title
        },
      },
    },
  ]
}

options.source
can be a string or a function. In this case, I wasn’t able to simply use
title
(maybe because we’re working with an object) so we use a function, destructure the second parameter to get
parent
, and then get title from that. 🤷‍♂️

// products.js

export default {
  name: 'products',
  type: 'document',
  fields: [
    {
      title: 'Variants',
      name: 'variants',
      type: 'array',
      of: [
        {
          title: 'Variant',
          type: 'productVariant',
        },
      ],
    },
  ],
  preview: {
    select: {
      variant0: 'variants.0.title',
      variant1: 'variants.1.title',
      variant2: 'variants.2.title',
      variant3: 'variants.3.title',
    },
    prepare: ({...variants}) => {
      const productVariants = Object.values(variants).filter(Boolean);
      return {
        title: `Variants: ${productVariants.length > 0 ? productVariants.join(', ') : 'None'}`,
      }
    }
  }
}
Here we get an arbitrary number of variants (I used 4), spread them into the prepare function in preview, filter out any undefined variants, and return them in a comma-separated list.

If I misunderstood what you’re after please follow up and let me know!
Jun 24, 2021, 3:54 AM
thanks
user A
you solved it with the first answer. I wasn't sure of how to use
source
. It wasn't as straight forward as console logging my
productVariant.js
and trying to identify the data structure to query. For example I knew I had to pass in some arguments but never knew it was
{parent}
.
Jun 24, 2021, 6:24 AM
now it's done and im able to set the
title
as the slug.
Jun 24, 2021, 6:25 AM
I'm now wondering what's the best practice on Gatsby should I wish to render a page for my product variant. I don't want the page component to change but i only want to update certain fields. E.g. Price. I'd also like to navigate to a new route e.g.
/product/variant-a
from
/product
.
I used do this in react a couple years ago with
react-router
? I remember passing the props and then setting the state on the component with the new props or something along those lines. However with Gatsby im not sure what should be the approach. I pinged on the Gatsby discord but havent received a reply so I'm trying my luck here 🤞
Jun 24, 2021, 12:36 PM
Thank you, that’s good feedback and I’ll make sure to pass it along. I think I originally got it from the second code block here but I’m not sure it’s listed out anywhere.
For the routes, perhaps you could take a look at the
Kitchen Sink starter , which separates the pages from the routes. Is that what you’re after?
Jun 24, 2021, 5:52 PM
user A
What i'm trying to achieve is more like what you see here:

https://www.patternbrands.com/shop/nesting-trays/?variant=38044220195013


?variant=38044220195013
is one of the color of the products, but on the same page I could click on another color which then changes the url to
?variant=38044220227781
instead. However, it's still largely the same react component with minor changes such as the image itself.
Jun 27, 2021, 8:50 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?