I created a react app with many nested routes
.
One of my nested route is using a backend api that returns a complete HTML content
.
And I need to display that exact content with same HTML and styling in my UI.
I'm able to successfully achieve it by manipulating the DOM according to axios response using createElement
and appendChild
inside useEffect
method.
But, the whole philosophy behind using react is, to NOT modify the DOM and let react work on it by simly updating the states or props.
My question is: Is there a cleaner way to use api returned HTML in a react app?
Here is sample relevant code:
Item.js
...
...
useEffect( ()=>{
const fetchAndUpdateItemContent = async () => {
try {
const response = await axios.get(url);
var contentDiv = document.createElement("div");
contentDiv.innerHTML = response.data.markup;
document.getElementById(‘itemContent’)
.appendChild(contentDiv);
} catch (err) {
.....
console.error(err);
......
}
}
};
fetchAndUpdateItemContent();
},[itemId])
return (
<div id=‘itemContent'/>
);
}
What did NOT work
Ideally I should be able to have a state as itemContent
in Item.js
and be able to update it based upon server response like this. But when I do something like below, whole HTML markup is displayed instead of just the displayable content.
const [itemContent, setItemContent] = useState(‘Loading ...');
...
useEffect( ()=>{
const fetchAndUpdateItemContent = async () => {
try {
const response = await axios.get(url);
setItemContent(response.data.markup)
} catch (err) {
.....
console.error(err);
......
}
}
};
fetchAndUpdateItemContent();
},[itemId])
return (
<div id=‘itemContent'>
{itemContent}
</div>
You're actually trying to convert an HTML string to a JSX. You can assign it into react component props called dangerouslySetInnerHTML
const Item = () => {
const yourHtmlStringResponse = '<h1>Heading 1</h1><h2>Heading 2</h2>'
return <div dangerouslySetInnerHTML={{__html: yourHtmlStringResponse}}></div>
}
You can try it here dangerouslySetInnerHTML-Codesandbox