Bardo_J
Bardo_J

Reputation: 51

How to output Contentful text as HTML instead of a string in Gatsby?

I can't get a long text field in Contenful to output properly in Gatsby.

I've tried:

const ProjectPost = ({ data }) => {
  const { title, body } = data.contentfulProject
  return (
    <Layout>
      <SEO title={title} />
      <div className="blogpost">
        <h1>{title}</h1>
        <div>{body.body}</div>
      </div>
    </Layout>
  )
}

export default ProjectPost

export const pageQuery = graphql`
  query($slug: String!) {
    contentfulProject(slug: { eq: $slug }) {
      title
      slug
      body {
        body
      }
    }
  }
`

that {body.body} outputs the content without any markup. It's just a few paragraphs of wrapped in quotes.

If I do:

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

const ProjectPost = ({ data }) => {
  const { title, body } = data.contentfulProject
  return (
    <Layout>
      <SEO title={title} />
      <div className="blogpost">
        <h1>{title}</h1>
        <div>{body.childMarkdownRemark.html}</div>
      </div>
    </Layout>
  )
}

export default ProjectPost

export const pageQuery = graphql`
  query($slug: String!) {
    contentfulProject(slug: { eq: $slug }) {
      title
      slug
      body {
        childMarkdownRemark {
          html
        }
      }
    }
  }
`

it outputs HTML wrapped in quotes, but isn't parsed as HTML in the browser. What am I doing wrong?

Upvotes: 0

Views: 2422

Answers (1)

stef
stef

Reputation: 14268

There are certain security issues around inserting HTML directly from a CMS into a React component, but if you are satisfied that your setup is sufficiently secure you could use the special dangerouslySetInnerHTML React attribute which takes a string of HTML and converts it into actual markup.

Use this wisely and take a moment to read up on some of the security issues here, but replacing your <div> with the following should display the actual HTML from your CMS.

<div dangerouslySetInnerHTML={{ __html: body.childMarkdownRemark.html }}></div>

Upvotes: 2

Related Questions