EDIT: better explanation
The context:
I receive some plain HTML code from a 3rd server, which I want to
The vanilla JS approach
id
getElementById
, as usualThe React approach
ReactDOMServer.renderToString
ReactDOM.render()
, the problem is that the render
method takes its time, so that if in the next line I try to use the ref that exists in the inserted component, is not yet thereThe question
useEffect
with a []
dependencies, but here I am rendering
the component when the app is already mountedref
, but for sure there has to be something betterThis code fails, because when the ref
is rendered it is still not available, so ref.current
is undefined
How can I wait for it?
EDIT: I provide the code that works but through direct DOM, which I assume should be avoided
import React, { useRef, useEffect } from "react";
import ReactDOM from "react-dom";
export default function App() {
const myref = useRef();
useEffect(() => {
const Com = () => <div ref={myref}>hello</div>;
ReactDOM.render(<Com />, document.getElementById("container"));
console.log(myref.current); // undefined
document.getElementById('container').textContent = "direct DOM works"
// the next line fails since the ref is not yet available
// myref.current.textContent = "but this REF is not available"; // fails
}, []);
const plainhtml = '<div><div id="container"></div><div>some more content</div><div id="another">even more content</div></div>'; // this is some large HTML fetched from an external server
return (
<div>
<h1>Hello CodeSandbox</h1>
<div dangerouslySetInnerHTML={{ __html: plainhtml }} />
</div>
);
}
I need to use a callback ref but encapsulating it within useCallback
to make sure it only rerenders with the dependencies indicated (i.e. none []
), so that it is only executed when the component changes (as explained here)
import React, { useEffect, useCallback } from "react";
import ReactDOM from "react-dom";
export default function App() {
const measuredRef = useCallback(node => {
if (node !== null) {
node.textContent = "useCallback DOM also works";
}
}, []);
useEffect(() => {
const Com = () => <div ref={measuredRef}>hello</div>;
ReactDOM.render(<Com />, document.getElementById("container"));
document.getElementById("container").textContent = "direct DOM works";
}, []);
const plainhtml = '<div id="container"></div>';
return (
<div>
<h1>Hello CodeSandbox</h1>
<div dangerouslySetInnerHTML={{ __html: plainhtml }} />
</div>
);
}