Sam
Sam

Reputation: 2331

Injecting gatsby-image into html created from markdown using ReactDOMServer.renderToString

Minimum Reproducible Example on Github


I'm trying to inject some images into my pages created from markdown. I'm trying to do this using ReactDomServer.renderToString()

const componentCreatedFromMarkdown = ({data}) => {
...    
    useEffect(() => {
        const injectDivs = Array.from(document.getElementsByClassName('injectDivs'))
        injectDivs.forEach((aDiv) => {
            aDiv.innerHTML = ReactDOMServer.renderToString(<Img fluid={data.allFile.edges[0].node.childImageSharp.fluid} />)
        }
    })
...
}

The img is showing as a black box, if I right click the image I can open it in a new tab, which shows the image as it is supposed to be.


enter image description here

Upvotes: 5

Views: 629

Answers (3)

JuanCaicedo
JuanCaicedo

Reputation: 3428

How I understand the problem

  • The image html is correctly inserted into the page

  • gatsby-image loads the lowest quality image and applies some inline styles. All that information is present in the html) This is done to enable the blur-up effect on the image for a better UX.

  • The client side code that would load a higher resolution image and remove the inline styles is never applied.

Useful diagnostic information

  • The function inside useEffect does not get run on the server-side, but rather on the client after the component has mounted. It's possible to verify this by adding a console.log statement inside the effect and seeing that it is logged on the browser's console.

Source of the problem

  • ReactDOMServer.renderToString() only builds the HTML that's required by a component, it then requires the component to be hydrated.

Direct fix

  • You can use ReactDOM.render to put the image on the page, given that the effect will execute client side. I have a PR showing that here.

Recommended approach

Hope that helps! 😄

Upvotes: 3

Yoandry Collazo
Yoandry Collazo

Reputation: 1212

I think the problem could be in the useEffect

const componentCreatedFromMarkdown = ({data}) => {

...    
    useEffect(() => {
        const injectDivs = Array.from(document.getElementsByClassName('injectDivs'))
        injectDivs.forEach((aDiv) => {
            aDiv.innerHTML = ReactDOMServer.renderToString(<MyComponent args={myArgs} />)
        }
    },[])
...
}

I think you should try to add useEffect(()=>{},[]), the second argument to refresh the image only when the component is mounted, without this the image will be refreshed each time.

Upvotes: 0

ShinaBR2
ShinaBR2

Reputation: 2705

I have faced this problem before with my first Gatsby project. The problem similar to this chat and the error image issue here.

If you replace GatsbyImageSharpFixed_withWebp_tracedSVG like they talked in spectrum chat above, or this is my current code for example, basically is related to WebP new image format.

export const query = graphql`
  query {
    allImageSharp {
      edges {
        node {
          fluid(maxWidth: 110) {
            aspectRatio
            originalName
            sizes
            src
            srcSet
            srcWebp
            tracedSVG
          }
        }
      }
    }
  }
`;

Hope this help.

Upvotes: 0

Related Questions