EDIT: better explanation
The context:
I receive some plain HTML code from a 3rd server, which I want to
- insert in my React app
- modify it
The vanilla JS approach
- I can modify the string with regex and add any HTML tag with an
id
- Then I can modify these elements through
getElementById
, as usual
The React approach
- I shouldn't use the DOM
- Then I should insert within the string some components that have a React ref inside
- The opposite (to insert some React components as plain HTML) would be through
ReactDOMServer.renderToString
- So, when I inject the components with
ReactDOM.render()
, the problem is that therender
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 there
The question
- How to do it? Usually I would put the code within a
useEffect
with a[]
dependencies, but here I amrendering
the component when the app is already mounted - A quick workaround is to just do an async wait of 500 ms, and then I can access the
ref
, but for sure there has to be something better
This 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>
);
}
ReactDOM.render
inside auseEffect
? You should just render it as a child, that way you would be able to use state to set the text content – SeminaltextContent
? – Anesthetizeplainhtml
is available (fetched from an external server), but the code example doesn't need to include this – Camelback.render()
, but then when I want to use the refs they're not available (they are if I wait few milliseconds). So the question is how to have access to them (which is what the code example shows) – Camelback