Unlock seamless workflows and faster delivery with our latest releases ā€“ get the details

PortableText not showing up in browser for a Product component in an ecommerce project

3 replies
Last updated: Aug 30, 2022
Hi everyone! I am trying to display the body data from a Product component with PortableText, and cannot seem to get it to show up in the browser. I had this exact same setup working perfectly with a blog, and was able to fetch and display the Body data, however when I am fetching data for a 'Product' and want to display the text in the 'body', it doesn't seem to show up on this ecommerce project, but it DOES show up on the blog project. Here is the [slug].js file, can anyone tell me why PortableText isn't showing up, but everything else is?

import Link from "next/link";
import { useRouter } from "next/router";
import groq from "groq";
import {
	PortableTextComponentsProvider,
	PortableText,
} from "@portabletext/react";
import { client } from "../../lib/sanity";
import imageUrlBuilder from "@sanity/image-url";

const builder = imageUrlBuilder(client);
function urlFor(source) {
	return builder.image(source);
}

const ptComponents = {
	types: {
		image: ({ value }) => {
			if (!value?.asset?._ref) {
				return null;
			}
			return (
				<img
					alt={value.alt || " "}
					loading="lazy"
					src={urlFor(value).width(320).height(240).fit("max").auto("format")}
				/>
			);
		},
	},
	block: {
		normal: ({ children }) => <p>{children}</p>,
	},
};

export default function Product({ products }) {
	const router = useRouter();
	if (router.isFallback) {
		return (
			<section>
				<h1>Loading...</h1>
			</section>
		);
	}
	const {
		defaultProductVariant = {},
		title = "Missing title",
		blurb,
		body = [],
	} = products;
	const { images, price = "" } = defaultProductVariant;

	return (
		<article>
			<h1>{title}</h1>
			<p>${price}</p>
			<hr />
			<img src={urlFor(images[0]).width(300)} />
			<PortableText value={body} components={ptComponents} />
			<p>{blurb.en}</p>
			<Link href="/">
				<a>Back home</a>
			</Link>
		</article>
	);
}

const query = groq`*[_type == "product" && slug.current == $slug][0]{
    title,
    image,
    price,
	body,
    blurb,
    "slug": slug.current,
    defaultProductVariant
}`;

export const getStaticProps = async (context) => {
	const { slug = "" } = context.params;

	const products = await client.fetch(query, { slug });

	return {
		props: {
			products,
		},
	};
};

export async function getStaticPaths() {
	const paths = await client.fetch(
		groq`*[_type == "product" && defined(slug.current)][].slug.current`
	);

	return {
		paths: paths.map((slug) => ({ params: { slug } })),
		fallback: false,
	};
}
Aug 30, 2022, 10:25 PM
Hi User. I see you have
blurb.en
and am curious if you also have that property on
body
. Could you try using
body.en
as your portable text value?
Aug 30, 2022, 10:36 PM
That did it! Thank you! I was looking through the schema earlier and noticed the type being localeBlockType, so this makes total sense.
Aug 30, 2022, 10:44 PM
Great! Happy to hear it. šŸ˜€
Aug 30, 2022, 10:45 PM

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?