Bridging CMS content and react components via shortcodes
Tags: react, cms, shortcode, blogging
Published: 2020-08-04 22:24:23

Recently I've taken up blogging as it were. I'm more of a developer than a writer but when it comes to the blog I thought it would be nice to use a proper CMS instead of coding in paragraph tags or writing in markdown. I don't need to make writing any harder than it is.

The problem that comes up as a developer writing with a CMS is that there's no bridge that allows you to mix a little code in with your content. If you're writing — you're writing. If you're coding — you're coding. There's no mingling going on. I want them to get to know each other.

Let's say I want to include an interactive or live map or chart that I built like I did in my [APIs post](https://joeczubiak.com/joes-apis). There's really not a great way to do that, especially in the middle of the content. We could write something custom into our post template to add a component at the end of a certain post but that's never a good idea.

This is where Shortcodes come in. Shortcodes is a concept popularized by [WordPress](https://wordpress.com/support/shortcodes/) in which you can insert a short snippet into square brackets, for example [contact-form]. Where you place the shortcode in your content is where the actual component will load. 

I thought it would be nice to create my own implementation of shortcodes for my blog so I can include my custom react components into my post by adding a simple shortcode. This creates the bridge between CMS and code that I was missing.

## Diving in
We are using React in this example. The CMS that you use does not matter. I'm borrowing the concept from WordPress but went a different way in implementation; we're not going to use square brackets but instead a new html tag `<sc>` for shortcode. This is not an existing tag but rather a tag we are creating so that we can find our shortcodes when we render our page.

## The CMS
At the end of this process we will be able to insert an html snippet into our post in the CMS and use our shortcode tag like this.

`<sc comp="ContactForm">Contact Form</sc>`

We define an attribute called 'comp' (component), this will specify which component we use to render the shortcode. We also should include some text in-between the tags to remind us what is loading here because when you are looking at the text in your CMS, the shortcode will look blank and you won't remember that you have a shortcode there unless you put in this descriptive text.

## Rendering the content
The trick to making this work is running an html parser instead of simply loading in the html. You might be used to loading your content with something like `<div dangerouslySetInnerHTML={{ __html: post.html }} />`. In our version we are going to replace that with our own implementation so it looks like `<HtmlParser html={post.html} />`.

Now we need to build our HtmlParser. Our component will rely on the [html-react-parser](https://www.npmjs.com/package/html-react-parser) library. You will need to include that with your package manager.

```jsx
import React from 'react'
// import your components the shortcodes reference.
import ContactForm from 'components/ContactForm'
import parse from 'html-react-parser'

const HtmlParser = ({ html }) => {
  // Replace shortcodes with their react component counterpart
  const replace = (domNode) => {
    // If we find the '<sc>' tag then we need to replace it.
    if (domNode && domNode.name === `sc` && domNode.attribs) {
      if (domNode.attribs.comp === `ContactForm`) {
        return (
          <ContactForm />
        )
      } else if (domNode.attribs.comp === `AnotherComponent`) {
        return (
          <AnotherComponent />
        )
      }
    }

    return domNode
  }

  return (
    parse(html, { replace })
  )
}
export default HtmlParser
```

Notice that we parse through the html and find the <sc> tags, we then use the comp attribute to check if it's an existing component and then explicitly load the component. For any new shortcodes, you'll have to add it to the HtmlParser.

## Now they're mingling
Now the code and content are talking to each other. This opens a lot of doors for making creative posts.


There are so many ways we could have gone about creating our shortcode system. This is just a starting point to help you think about bridging the CMS code gap. Further improvements could include allowing props to be passed to the components.