Tips for using block-content-to-react in a Gatsby app with GraphQL data
13 replies
Last updated: Apr 24, 2020
U
Are there any videos on how to use the block-content-to-react (https://github.com/sanity-io/block-content-to-react/blob/master/README.md ) inside a gatsby app where I’m already getting the data via gatsby graphql api already?
Apr 19, 2020, 4:09 AM
C
Hey Saia, I don’t know about any good videos but I can give you some tips.Remember that you cannot (you can with some hacks, but I don’t know how) run GROQ queries in Gatsby, you have to use GraphQL; Use graphiql to create your queries
Then install the block content component as instructed in the repo.
Import it with a const
Then run it with your data fields, you usually want the fields starting with _raw for block content
If you want to do things like add CSS classes to your block content data you’ll need to use a serializer.
Here is one that I used recently, note that this is a full component. You can also just define the serializer and pass it to block content like this
My component that serializes looks like this
I just import it in my files and run it, I don’t have to pass serializers to it as it already has one. But I do have to pass blocks
Then install the block content component as instructed in the repo.
Import it with a const
import BlockContent from "@sanity/block-content-to-react"
<BlockContent blocks={blocks} />
If you want to do things like add CSS classes to your block content data you’ll need to use a serializer.
Here is one that I used recently, note that this is a full component. You can also just define the serializer and pass it to block content like this
<BlockContent blocks={blocks} serializers={someSerializer} />
My component that serializes looks like this
import BaseBlockContent from "@sanity/block-content-to-react" import React from "react" import { Link } from "gatsby" const serializers = { types: { block(props) { switch (props.node.style) { case "h1": return <h1 className="text-center">{props.children}</h1> case "h2": return <h2 className="text-center">{props.children}</h2> case "h3": return <h3 className="text-center">{props.children}</h3> case "h4": return <h4 className="text-center">{props.children}</h4> case "blockquote": return <blockquote>{props.children}</blockquote> default: return <p className="inspirationText">{props.children}</p> } }, }, marks: { internalLink: ({ mark, children }) => { const { slug = {} } = mark const href = `/${slug.current}` return <Link to={href}>{children}</Link> }, externalLink: ({ mark, children }) => { const { blank, href } = mark return blank ? ( <a href={href} target="_blank" rel="noopener noreferrer"> {children} </a> ) : ( <a href={href}>{children}</a> ) }, }, } const BlockContent = ({ blocks }) => ( <BaseBlockContent blocks={blocks} serializers={serializers} /> ) export default BlockContent
Apr 19, 2020, 11:42 AM
U
In the file where I want to render the rich text data, I have my graphql query like so:
export const query = graphql` query($slug: String!) { sanityProject(slug: { current: { eq: $slug } }) { title author { name } slug { current } _rawDescription image { asset { fluid { ...GatsbySanityImageFluid } } } } } `
Apr 19, 2020, 11:43 PM
U
then I have my component, like so:
const PostTemplate = ({ data: { sanityProject: post } }) => { // const htmlDescription = post.description.split("\n").join("<br />") console.log("post", post) return ( <> <Header /> <Layout> <h1>{post.title}</h1> <p css={css` font-size: 0.75rem; `} > Posted by {post.author.name} </p> <br /> {post.image && <Img fluid={post.image.asset.fluid} alt={post.title} />} <br /> {/* {post._rawDescription.map(content => ( <pre>{JSON.stringify(content, null, 2)}</pre> ))} */} <ReadLink to="/">← back to all posts</ReadLink> </Layout> </> ) } export default PostTemplate
Apr 19, 2020, 11:44 PM
U
What’s the recommended way to rendering my data from sanity with the rich text styles here ^ in my Gatsby app?
Apr 19, 2020, 11:46 PM
C
Why do you do a
the _raw elements are great for block content, import the block content like I showed in my earlier code (const BlockContent…)
then run <BlockContet blocks={post._rawDescription} />
Note that if you have any custom types you may need a serializer
{post._rawDescription.map(content => ( <pre>{JSON.stringify(content, null, 2)}</pre>
then run <BlockContet blocks={post._rawDescription} />
Note that if you have any custom types you may need a serializer
Apr 20, 2020, 7:04 AM
N
user C
is spot on ... just for some extra context, below is how i'm running my PortableText via serializersquery:
fragment SingleArticleFragment on SanityArticle { title slug { current } ... excerpt _rawBodyCopy(resolveReferences: { maxDepth: 10 }) ... } }
{_rawBodyCopy && <PortableText _blocks_={_rawBodyCopy} />}
PortableText.js component:
import React from 'react' import BlockContent from '@sanity/block-content-to-react' import serializers from './Serializers' const PortableText = ({ blocks }) => ( <BlockContent blocks={blocks} serializers={serializers} /> ) export default PortableText
import InlineImage from './InlineImage' const serializers = { types: { inlineImage: InlineImage, } } export default serializers
Apr 20, 2020, 1:50 PM
N
also, here's another serializers i have in different project .. the rest of the items are basically the same.
This one just has more components in the PortableText that I can insert during authoring.
hope this helps
This one just has more components in the PortableText that I can insert during authoring.
import Image from './Image' import VideoBlock from './Video' import VideoEmbedBlock from './VideoEmbedBlock' import GalleryBlock from './GalleryBlock' import MapBlock from './MapBlock' import InstagramBlock from './InstagramBlock' const serializers = { types: { imageFull: Image, video: VideoBlock, gallery: GalleryBlock, googleMyMap: MapBlock, instagramPost: InstagramBlock, videoEmbed: VideoEmbedBlock } } export default serializers
Apr 20, 2020, 1:52 PM
R
anyone have any idea how
serializers.containerworks? I need some specific wrapping container but docs don't really make it clear how to do it 😕
Apr 24, 2020, 9:33 AM
R
const serializers = { container: YourReactElementHere, }
Apr 24, 2020, 9:37 AM
R
const serializers = { container: ({ children }) => ( <Stack direction="vertical" gap={3}> {children} </Stack> ), }
👌
Apr 24, 2020, 9:39 AM
R
user Y
i think it makes sense for this to be in the docs? Want me to add a PR?Apr 24, 2020, 9:39 AM
K
sure! You’re thinking the README.md for the library?
Apr 24, 2020, 9:46 AM
R
Yep pretty much. Maybe it should be in all the READMEs for the other libs as well actually 🤔
Apr 24, 2020, 9:48 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.