It’s incredibly hard to find a way to inject HTML DOM elements in React. Yeah, we probably should migrate them to react, etc, etc, but sometimes this is not possible: suppose you have a library that returns an HTMLElement, with handlers already set, callbacks, etc, but you’re rendering your app in React. Can you preserve everything?

And the answer is, yes. It’s incredibly simple too. But for some reason, there’s almost zero documentation, and even React’s site is confusing to say the least. So, as this is a quick post, let’s go directly to the Javascript code:

// Assume you have React already, either globally
// or with import..., or require..

function wrapInReact(htmlElement) {
  const ref = React.useRef(null)
  React.useEffect(() => {
    if(ref.current) {
      ref.current.appendChild(htmlElement)
    }
  }, [ref.current])

  return React.createElement("div", {ref: ref})
}

// Use with:
const div = document.createElement("div")
div.innerText = "Hello, world!"
const MyComponent = wrapInReact(htmlElement)
// Then proceed to render things

Or with ClojureScript:

(defn- html->react [html-element]
  (let [ref (. react useRef nil)]
    (. react useEffect
      #(when-let [e (.-current ref)] 
         (.appendChild e html-element))
      #js [(.-current ref)])
    (. react createElement "div" #js {:ref ref})))

;; Use with:
(def div (doto (js/document.createElement "div") 
               (aset "innerText" "Hello, world")))
;; For example, to use it in Reagent:
[:f> #(html->react div)]

And, that’s all. Why it is so hard to find this? No idea…