Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
178
rated 0 times [  184] [ 6]  / answers: 1 / hits: 15872  / 4 Years ago, fri, april 24, 2020, 12:00:00

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 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 there



The question




  • How to do it? Usually I would put the code within a useEffect with a [] dependencies, but here I am rendering 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?



codesandbox



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>
);
}

More From » reactjs

 Answers
10

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)



codesandbox



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>
);
}

[#51005] Thursday, April 16, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kayden

Total Points: 546
Total Questions: 102
Total Answers: 95

Location: Virgin Islands (U.S.)
Member since Fri, Mar 4, 2022
2 Years ago
;