0

I'm using NextJs. I have an html string that is fetched from the server. It represents a blog post and contains several <img> tags. I'm currently rendering the post like this:

const blogpostHtml = "..." // an html string that comes from the server
return (
  ...
  <div
    dangerouslySetInnerHTML={{__html: blogpostHtml}}
  />
  ...
)

And it works fine. However, I'd like to add functionality to the images. I found this library that accomplishes what I want with an uncontrolled component:

  ...
  <Zoom>
    <img
      alt="some alt"
      width="500"
      src="the image url"
    />
  </Zoom>
  ...

However, I noticed that I can't simply insert the Zoom tags because it's interpreted as a raw html tag instead of a component. And if I try to render it to a string it loses functionality.

let html = ReactDOMServer.renderToString(
  <Zoom>
    <img
      alt="some alt"
      width="500"
      src="the image url"
     />
   </Zoom>
 )

 return (
   ...
   <div
     dangerouslySetInnerHTML={{__html: html}}
   />
   ...
)

As you can see, the resulting html is the same as using the Zoom component as intended, but the button loses its event

As you can see in the image, the resulting html is the same as using the Zoom component as intended, but the button loses its event

So how can I combine the html string from the server and the uncontrolled Zoom component to achieve what I want?

1

1 Answer 1

1

Thanks to William's answer in the comments I got this solution

import Zoom from 'react-medium-image-zoom'
import ReactDOM from 'react-dom'
import { useEffect } from 'react'

  const Index = () => {
   const html = ` 
   <p>This is some text</p>
     <img src="some-img-src.jpg"/>
   <p>More text here</p>
   `

   useEffect(() => {
     // 1. extract imgs and src
     const imgs = document.getElementsByTagName('img')
     const srcArray = Array.from(imgs).map(img => img.src)

     // 2. wrap images with div then replace each div using ReactDOM.render
     for (let i = 0; i < imgs.length; i++) {
       const wrapper = document.createElement('div')
       wrapper.setAttribute('id', `img-${i}`)

       imgs[i].parentNode.insertBefore(wrapper, imgs[i])
       wrapper.appendChild(imgs[i])

       ReactDOM.render(
         <Zoom>
           <img src={srcArray[i]} />
         </Zoom>,
         document.querySelector(`#img-${i}`)
       )   
     }   
   }, []) 

    return (
     <>  
        <div
          dangerouslySetInnerHTML={{
            __html: html
          }}  
        />
      </> 
    )
  }

  export default Index
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.