Marie-Anne Melis

Wordpress and Joomla developer, learning new stuff

Getting my react-gatsby metadata to work

This morning I discovered with view-source, after using this seo-testtool, that my source did not contain a <title></title> and metadescription tag as I expected. In my opinion I had done what should be done, so why?

My start situation was copied from someone else and looked like this:

import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

function SEO({ description, lang, meta, title }) {
//do some stuff and put the results via helmet into the <head> of page.
}

Debugging learned that all the appropriate values were available in the SEO-function and also in the elements at the website itself but not in the Gatsby source.

I googled a lot, as usual, and read about react-helmet-async, tried that one before as I mentioned in another blog and was not in the mood to try it again. It turned out to be back to the Gatsby basics.

Solution part 1

I bumped into the gatsby-plugin-react-helmet and the description was very clear about what I was missing :

With this plugin, attributes you add in their (React) component, e.g. title, meta attributes, etc. will get added to the static HTML pages Gatsby builds.

I installed the plugin and added the plugin to my gatsby-config.js and was sure life would be fine and it was, partially. There was a <title></title> but it was empty!

Remark: when you create a new gatsby project from scratch this plugin is actually installed, but when I was messing around with the seo some warnings related to react-helmet I must have removed it.

Solution part 2

I am a mix between “just try” and read the documentation. The documentation of the gatsby-plugin-react-helmet has a special paragraph about “Compatibility with React 16.8 useEffect hook”:

To ensure everything is running smoothly when using these technologies together, make sure to validate the following:

………

You are importing React Helmet using import { Helmet } from 'react-helmet' rather than the old import Helmet from 'react-helmet'

Yes I was, no I didn’t and yes I changed the import to { Helmet }.

IT WORKED! Sorry, still happy. This is not the solution for everyone but if I save another person some time or trouble that would be nice.

To-remember for the near future

Complete the metatags and remember the format for my function.

meta={[
{ property: 'og:title', content: `${seo.title} | Code ` },
{ property: 'og:url', content: seo.url },
{ property: 'og:image', content: seo.image },
{ property: 'og:image:type', content: 'image/jpeg' },
{ property: 'twitter:image:src', content: seo.image },
{ property: 'twitter:title', content: `${seo.title} | Code Mochi` },
{ property: 'twitter:description', content: seo.description },
      ]}

Which in my case goes into this component:

/**
 * SEO component that queries for data with
 *  Gatsby's useStaticQuery React hook
 *
 * See: https://www.gatsbyjs.org/docs/use-static-query/
 */

import React from "react"
import PropTypes from "prop-types"
import {Helmet} from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

function SEO({ description, lang, meta, title }) {
    const { site } = useStaticQuery(
        graphql`
      query {
        site {
          siteMetadata {
            title
            description
            author
          }
        }
      }
    `
    )

    const metaDescription = description || site.siteMetadata.description


    return (
        <Helmet
            htmlAttributes={{
                lang,
            }}
            title={title}
            titleTemplate={`%s | ${site.siteMetadata.title}`}
            meta={[

                {
                    name: `Content-Type`,
                    content: 'text/html; charset=utf-8',
                },
                {
                    name: `description`,
                    content: metaDescription,
                },
                {
                    property: `og:title`,
                    content: title,
                },
                {
                    property: `og:description`,
                    content: metaDescription,
                },
                {
                    property: `og:type`,
                    content: `website`,
                },
                {
                    name: `twitter:card`,
                    content: `summary`,
                },
                {
                    name: `twitter:creator`,
                    content: site.siteMetadata.author,
                },
                {
                    name: `twitter:title`,
                    content: title,
                },
                {
                    name: `twitter:description`,
                    content: metaDescription,
                },
            ].concat(meta)}
        />
    )
}

SEO.defaultProps = {
    lang: `en`,
    meta: [],
    description: ``,
}

SEO.propTypes = {
    description: PropTypes.string,
    lang: PropTypes.string,
    meta: PropTypes.arrayOf(PropTypes.object),
    title: PropTypes.string.isRequired,
}

export default SEO