使用 ReactDOMServer.renderToString 将 gatsby-image 注入到从 markdown 创建的 html

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

Minimum Reproducible Example on Github


我正在尝试将一些图像插入到我从 markdown 创建的页面中。我正在尝试使用 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} />)
        }
    })
...
}

img 显示为黑框,如果我右键单击该图像,我可以在新选项卡中打开它,它会显示图像的本来面目。


我之前在第一个 Gatsby 项目中遇到过这个问题。 类似这样的问题chat and the error image issue here.

如果你像他们在上面的频谱聊天中所说的那样替换 GatsbyImageSharpFixed_withWebp_tracedSVG,或者这是我当前的代码,例如,基本上与 WebP 新图像格式有关。

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

希望对您有所帮助。

我认为问题可能出在 useEffect

const componentCreatedFromMarkdown = ({data}) => {

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

我觉得你应该尝试添加useEffect(()=>{},[]),第二个参数只在组件挂载时刷新图片,没有这个每次都会刷新图片。

我是怎么理解这个问题的

  • 图像html已正确插入页面

  • gatsby-image 加载最低质量的图像并应用一些内联 样式。所有这些信息都存在于 html) 这样做是为了 启用图像模糊效果以获得更好的用户体验。

  • 从未应用加载更高分辨率图像和删除内联样式的客户端代码。

有用的诊断信息

  • useEffect 中的函数不会在服务器端获得 运行,而是在组件安装后在客户端获得。可以通过在效果中添加 console.log 语句并查看它是否已记录在浏览器的控制台上来验证这一点。

问题的根源

  • ReactDOMServer.renderToString() 仅构建组件所需的 HTML,然后它要求组件为 hydrated.

直接修复

  • 您可以使用ReactDOM.render将图像放在页面上,因为效果将在客户端执行。我有一个 PR 显示 here.

推荐方法

希望对您有所帮助!