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.
However, I don't see the yellow highlighting in my React frontend.
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>
);
}