Using WordPress Shortcode Functionality in Gatsby

Last Updated:
Shortcodes from WordPress in Gatsby

I have recently started updating a personal site of mine to include a newsletter signup form. I wanted to be able to include this manually wherever I wanted within article content.

As the backend (CMS) is WordPress, it made sense to use the functionality that is common place for WordPress users – short codes!

After a reasonable amount of Googling all I could find was a number of suggestions that I move to MDX. Not something I particularly want to do as this solution will eventually be rolled out to some of my clients sites.

Adding WordPress shortcodes to a Gatsby site seemed like it wasn’t going to be possible due. I initially looked into a custom resolved but this wasnt going to work for a number of reasons. And due to how gatsby-source-wordpress handles the data it felt too complex.

The Solution to WordPress Gatsby Shortcodes

Then I stumbled onto this super helpful package: html-react-parser

This package makes it possible to find a particular node within a HTML block, and maniplate it. Whether that be replacing it or removing it.

All my sites use a component to handle WYSIWYG content that is passed the raw HTML data from the WordPress content editor. I added the html-react-parser to this, and use it to swap out shortcode snippets and replace with specific components.

Here is an example of the solution. The shortcode used within the WordPress content is [newsletter-form].

import React from "react";
import { graphql } from "gatsby";
import parse from "html-react-parser";

// An example component so we have something to return.
const NewsletterSignupForm = () => <div>Example Form</div>;

// Util function to handle the shortcode find/replace.
const handleShortcodes = (node) => {
  // It seems all shortcodes are P tags.
  // So we check that the node has a type, and that that type
  // is a tag.
  if (node.type && node.type === "tag") {
    // If this tag has children, and it is the first child.
    // This may cause issues, but I have not had issues with it.
    // The first array is usually a shortcode is the first and
    // only child of a tag node.
    const shortcode = node.children[0]?.data;

    // If we find the shortcode string, replace it with
    // our component.
    if (shortcode === "[newsletter-form]") {
      return <NewsletterSignupForm />;
    }
  }

  // If nothing then return original node
  return node;
};

const Wysiwyg = ({ children }) => {
  const reactElements = parse(children || "", {
    replace: handleShortcodes,
  });

  return <div>{reactElements}</div>;
};

const PostTemplate = ({
  data: {
    wpPost: { content },
  },
}) => (
  <>
    {/** Other code has been removed **/}
    <Wysiwyg>{content}</Wysiwyg>
  </>
);

// Very basic query from gatsby-source-wordpress.
export const postQuery = graphql`
  query article($id: Int!) {
    wpPost(databaseId: { eq: $id }) {
      content
    }
  }
`;

export default PostTemplate;

 

Hopefully this article has helped, and if you have any questions you can reach me at: @robertmars

P.S. This is exactly how the below support component is injected into this page…

Related Posts

Helpful Bits Straight Into Your Inbox

Subscribe to the newsletter for insights and helpful pieces on React, Gatsby, Headless WordPress, and Jest testing type things.