2

I am trying to create a blog using Sanity Headless CMS and React for the frontend.

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. enter image description here However, I don't see the yellow highlighting in my React frontend.

enter image description here What am I missing?

The code snippets are as follows: sanityblog/schemas/blockContent.js

import React from "react";

/**
 * This is the schema definition for the rich text fields used for
 * for this blog studio. When you import it in schemas.js it can be
 * reused in other parts of the studio with:
 *  {
 *    name: 'someName',
 *    title: 'Some title',
 *    type: 'blockContent'
 *  }
 */

const highlightRender = (props) => (
  <span style={{ backgroundColor: "yellow" }}>{props.children}</span>
);

export default {
  title: "Block Content",
  name: "blockContent",
  type: "array",
  of: [
    {
      title: "Block",
      type: "block",
      // Styles let you set what your user can mark up blocks with. These
      // correspond with HTML tags, but you can set any title or value
      // you want and decide how you want to deal with it where you want to
      // use your content.
      styles: [
        { title: "Normal", value: "normal" },
        { title: "H1", value: "h1" },
        { title: "H2", value: "h2" },
        { title: "H3", value: "h3" },
        { title: "H4", value: "h4" },
        { title: "Quote", value: "blockquote" },
      ],
      lists: [{ title: "Bullet", value: "bullet" }],
      // Marks let you mark up inline text in the block editor.
      marks: {
        // Decorators usually describe a single property – e.g. a typographic
        // preference or highlighting by editors.
        decorators: [
          { title: "Strong", value: "strong" },
          { title: "Emphasis", value: "em" },
          {
            title: "Highlight",
            value: "highlight",
            blockEditor: {
              icon: () => "H",
              render: highlightRender,
            },
          },
        ],
        // Annotations can be any object structure – e.g. a link or a footnote.
        annotations: [
          {
            title: "URL",
            name: "link",
            type: "object",
            fields: [
              {
                title: "URL",
                name: "href",
                type: "url",
              },
              {
                title: "Open in new tab",
                name: "blank",
                description: "Read https://css-tricks.com/use-target_blank/",
                type: "boolean",
              },
            ],
          },
        ],
      },
    },
    // You can add additional types here. Note that you can't use
    // primitive types such as 'string' and 'number' in the same array
    // as a block type.
    {
      type: "image",
      options: { hotspot: true },
    },

    {
      type: "code",
    },
  ],
};

src/components/OnePost.js OnePost.js is responsible for rendering a single blog post.

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-11 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>
  );
}

HKS
  • 526
  • 8
  • 32

1 Answers1

2

You need to serialize the data.

You already do this for the code editor window, in your current serializer you say "if the type is code, run this component".

You need to do this for the syntax highlighter too, maybe something like this could work (have not tested this)

marks: {
  highlight: ({ children }) => {
    return <HighLightComponent children={children} />;
  },
},
sam_vimes
  • 94
  • 1
  • 9
  • You need to serialize the data. What does it mean? Also, what is this `Highlight` component and how do I use it? – HKS Apr 05 '21 at 10:55
  • The highlight component is just a mock component I made up. In there you can run the code you need to highlight. You could also just use the HTML-tag if you prefer. To "serialize" data basically just means translating it to the format you want. Sanity only provides JSON, not HTML. So you have to say "if sanity returns highlight, put it inside this HTML". You can see the structure if you run the GROQ query in Sanity Studio. See one of my serializers here, maybe it can give you some inspiration :) https://pastebin.com/KC19EWkH – sam_vimes Apr 05 '21 at 11:05
  • Thanks a lot Sam. You made my day. I have been struggling with this for days. I find Sanity documentation confusing. I will come back to you for help. I am making a blog with Sanity and React frontend. Thanks again. – HKS Apr 05 '21 at 12:06