How to create a serializer for highlighting text in Sanity.io React frontend

5 replies
Last updated: Apr 5, 2021
I have made a decorator for highlighting text. As you can see in the image below, in the editor, the highlighted text has yellow background color. However, I don't see the yellow highlighting in my React frontend. What am I missing?
Apr 2, 2021, 6:33 AM
Have you created a serializer for this decorator? https://www.sanity.io/docs/portable-text-to-react#rendering-custom-marks
Apr 2, 2021, 1:42 PM
I went through the links. However, I am not sure how do I implement a serializer for highlighting text. In the OnePost.js component (the component for rendering one single blog post) I have already a serializer for code block. So, how do I add another serializer for highlighting text and how would that serializer look? Pls. help.

OnePost.js
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import sanityClient from "../client.js";
import BlockContent from "@sanity/block-content-to-react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { coldarkDark } from "react-syntax-highlighter/dist/esm/styles/prism";

export default function OnePost() {
  const [postData, setPostData] = useState(null);
  const { slug } = useParams();

  const serializers = {
    types: {
      code: (props) => (
        <SyntaxHighlighter
          language={props.node.language}
          style={coldarkDark}
          showLineNumbers
          lineNumberStyle={{
            padding: "0 5px 0 0",
            fontSize: 14,
            borderRight: "1.5px solid darkgray",
            marginRight: "10px",
          }}
        >
          {props.node.code}
        </SyntaxHighlighter>
      ),
    },
  };

  useEffect(() => {
    sanityClient
      .fetch(
        `*[slug.current == $slug]{
          title,
          slug,
          mainImage{
            asset->{
              _id,
              url
             }
           },
         body,
        "name": author->name,
        "authorImage": author->image
       }`,
        { slug }
      )
      .then((data) => setPostData(data[0]))
      .catch(console.error);
  }, [slug]);

  if (!postData) return <div>Loading...</div>;

  return (
    <div className="col-sm-10 col-md-6 mx-auto mt-5">
      <div>
        <h1 className="font-weight-bold">{postData.title}</h1>
        <div>
          <h6 className="text-secondary">{postData.name}</h6>
        </div>
      </div>
      <div className="text-muted">
        <BlockContent
          blocks={postData.body}
          projectId={sanityClient.projectId}
          dataset={sanityClient.dataset}
          serializers={serializers}
        />
      </div>
    </div>
  );
}
Apr 2, 2021, 4:11 PM
Hi Hemant. In your serializers object (
const serializers = { … }
), you’ll notice a
types
object (where you defined
code
). That’s where you would define serializers for block types. Since highlighted text is a mark (a text child of a block—think inline elements), you want to add
marks
as a sibling of
types
and set up your serializer. Something like:

const serializers = {
  types: {
    code: (props) => ( ... ),
  },
  marks: {
    highlight: ({ children }) => (
      <span style={{ backgroundColor: 'yellow' }}>{children}</span>
    ),
  },
};
Apr 5, 2021, 5:57 PM
Thanks, Problem solved.
Apr 5, 2021, 6:47 PM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the 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?

Categorized in