Gatsby: dangerouslySetInnerHTML does not work on production builds

Created on 16 Jan 2019  路  12Comments  路  Source: gatsbyjs/gatsby

I'm transforming and adding frontmatter content from markdown to html to my page, with the help of showdown. Its working on develop builds, unfortunately in production builds the content is missing.

Here's the page code:

import React from "react";
import { Container, Col, Row } from "reactstrap";
import Grid3Column from "../components/Grid3Column";
import FullPageImg from "../components/FullPageImg";
import Metadata from "../components/Metadata";
import Accordeon from "../components/Accordeon";
import showdown from "showdown";

const converter = new showdown.Converter();

const IndexPage = ({ data }) => {
  const { frontmatter } = data.markdownRemark;
  return (
    <Container className="body__main">
      <Metadata
        title={frontmatter.title}
        description={frontmatter.description}
      />
      <Row>
        <Col>
          <h1 className="mainheader">{frontmatter.heading}</h1>
        </Col>
      </Row>
      <Row className="mb-4">
        <Col>
          <p
            dangerouslySetInnerHTML={{
              __html: converter.makeHtml(frontmatter.bodycopy1)
            }}
          />
        </Col>
      </Row>

      <FullPageImg image1={frontmatter.banner1.image1} />

      <Grid3Column
        callout1={frontmatter.grid1.callout1}
        callout2={frontmatter.grid1.callout2}
        callout3={frontmatter.grid1.callout3}
        image1_1={frontmatter.grid1.image1_1}
        image1_2={frontmatter.grid1.image1_2}
        image2_1={frontmatter.grid1.image2_1}
        image2_2={frontmatter.grid1.image2_2}
        image3_1={frontmatter.grid1.image3_1}
        image3_2={frontmatter.grid1.image3_2}
      />

      <Row className="mt-4">
        <Col>
          <p
            dangerouslySetInnerHTML={{
              __html: converter.makeHtml(frontmatter.bodycopy2)
            }}
          />
        </Col>
      </Row>

      <Row>
        <Col>
          <Accordeon
            title1={frontmatter.accordeon.title1}
            title2={frontmatter.accordeon.title2}
            title3={frontmatter.accordeon.title3}
            title4={frontmatter.accordeon.title4}
            title5={frontmatter.accordeon.title5}
            title6={frontmatter.accordeon.title6}
            image1={frontmatter.accordeon.image1}
            image2={frontmatter.accordeon.image2}
            image3={frontmatter.accordeon.image3}
            image4={frontmatter.accordeon.image4}
            image5={frontmatter.accordeon.image5}
            image6={frontmatter.accordeon.image6}
          />
        </Col>
      </Row>
    </Container>
  );
};

export default IndexPage;

export const IndexPageQuery = graphql`
  query IndexPageQuery($id: String!) {
    markdownRemark(id: { eq: $id }) {
      frontmatter {
        templateKey
        title
        heading
        description
        bodycopy1
        bodycopy2
        banner1 {
          image1 {
            image
          }
        }
        accordeon {
          image1
          image2
          image3
          image4
          image5
          image6
          title1
          title2
          title3
          title4
          title5
          title6
        }
        grid1 {
          callout1
          callout2
          callout3
          image1_1 {
            image
          }
          image1_2 {
            image
          }
          image2_1 {
            image
          }
          image2_2 {
            image
          }
          image3_1 {
            image
          }
          image3_2 {
            image
          }
        }
      }
    }
  }
`;

Thank you for the support,
Thomas

needs reproduction

Most helpful comment

@tbinte This is a bug in React https://github.com/facebook/react/issues/5479 and possible duplicate of #2750
Ran into this couple of days ago, possible work around is to avoid using dangerouslySetInnerHTML on p tags and use them within divs like this. https://github.com/gatsbyjs/gatsby/issues/2750#issuecomment-342245034

dangerouslySetInnerHTML={{ __html: `<div> ${data} </div>` }}

All 12 comments

Thank you for opening this @tbinte

Can you please link to a minimal reproduction for this?

@tbinte This is a bug in React https://github.com/facebook/react/issues/5479 and possible duplicate of #2750
Ran into this couple of days ago, possible work around is to avoid using dangerouslySetInnerHTML on p tags and use them within divs like this. https://github.com/gatsbyjs/gatsby/issues/2750#issuecomment-342245034

dangerouslySetInnerHTML={{ __html: `<div> ${data} </div>` }}

I can confirm, using div's instead of p solved the problem.

@tbinte thanks for letting us know that. I'll be closing this issue for now, if you need any further information regarding this please follow up on the issue I mentioned in the previous comment.

Just as a further note, I encountered this issue a couple days ago. I have reproduced the issue at this repository.

Swapping out <p dangerouslySetInnerHTML> for <div dangerouslySetInnerHTML> did the trick for me!

I spent couple of hours today trying to fix this before stumbling on this issue. Could we keep this issue open until it is fixed. Gatsby prod-build should match develop behavior, so this is indeed a bug. Right?

@ecstasy2 Unfortunately there are currently some differences in behaviour between gatsby develop and gatsby build because we don't do SSR during development.

This is why such issues occur in build and not during develop. We are looking at converging the behaviour between the two in https://github.com/gatsbyjs/gatsby/issues/10706

A bit annoying but glad to have found folks struggling with the same issue. Switching from p to div worked.

I did it with a div because of this thread, but actually is very anoying and somebody should explain a little bit more!

Found this on google and felt the need to add more context in case anyone else does the same. The reason this works for div but fails with p is due to the HTML spec itself and how p tags are defined. The closing tag for p is optional and nesting p tags is not valid.

For example, if you were to write the following:

<p class="outer">
  <p class="inner"></p>
</p>

This would result in (on render):

<p class="outer"></p>
<p class="inner"></p>
<p></p>

The outer element immediately closes itself when encountering a child p element as nesting these tags is invalid. This leaves us with a dangling closing tag </p> which automatically adds an opening tag to itself. You'll notice these 3 tags are all siblings (none have a parent/child relationship as originally written).

I still habe the same problem. dangerouslySetInnerHTML is not working in production mode on my netlify project https://thoughts-on-coding.netlify.app. It should show a summary at each card but dose it only after entering the post contents and going back afterwards.
I also tried @haxzie-xx solution but still have the same problem.

I'm using gatsby 2.29.1, the repository can be found here https://github.com/Ben1980/thoughts-on-coding

I still habe the same problem. dangerouslySetInnerHTML is not working in production mode on my netlify project https://thoughts-on-coding.netlify.app. It should show a summary at each card but dose it only after entering the post contents and going back afterwards.
I also tried @haxzie-xx solution but still have the same problem.

I'm using gatsby 2.29.1, the repository can be found here https://github.com/Ben1980/thoughts-on-coding

@Ben1980 You're using the Typography component from material-ui that renders to a p element which is an invalid use case of dangerouslySetInnerHTML. This isn't a bug with Gatsby or React necessarily, rather a poor choice of element to try and set content within. The HTML spec defines that the p tag cannot include block-level elements, including the p tag itself. See: Paragraph Spec

To fix:
From your codebase:

<Typography variant="body1" component="p" ... />

Try removing the component="p" prop, the Typography component should default to a span which allows setting inner HTML.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andykais picture andykais  路  3Comments

dustinhorton picture dustinhorton  路  3Comments

magicly picture magicly  路  3Comments

brandonmp picture brandonmp  路  3Comments

theduke picture theduke  路  3Comments