Reputation: 3705
What I want to do is to fetch a website, then convert it into HTML, but not put the entire HTML into the React DOM, first select an element (and obviously it's children), then put this specific element into the React DOM. What I want is something like this:
convertHtml = () => {
fetch(url)
.then(res => res.text())
.then(htmlString => {
/*for example the htmlString looks like this:
"<html>
<body>
<div>
<p id="elementWhatIWant">
I want to earn this element (not the text inside)
</p>
</div>
</body>
</html>"
*/
//what I want:
return stringToHtml(htmlString).getElementById("elementWhatIWant")
})
}
render = () => <div className="App">
{this.convertHtml()}
</div>
I did some research, but as I saw, there's only one way to get an element in React, and it's the ref. Because it's a string, we can't put ref on any element directly. The thing what I thought is that we can parse the string, and
elementWhatIWant
element, and put the ref on it as a string, orelementWhatIWant
element, search it's closing tag, and return just this part of the stringNeither of them seems like a good approach, that's why I'm asking: What is the best way to earn what I want?
Upvotes: 1
Views: 2525
Reputation: 22911
As previously mentioned, if these are simple HTML elements, you should consider using react-html-parser. It will solve your issue, in a much safer way, as opposed to dangerouslySetInnerHTML
below. See my codesandbox here for more info:
class App extends React.Component {
constructor() {
super();
this.state = {
html: null
};
this.fetchHtml = this.fetchHtml.bind(this);
}
async fetchHtml() {
const html = await ajaxPlaceholder();
console.log("Got new html!", html);
const parsed = $(html).find("span");
// From https://stackoverflow.com/a/5744268/4875631
this.setState({
html: parsed[0].outerHTML
});
}
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
Escaped: <div>{this.state.html}</div>
<br />
Not Dangerous: <div>{parser(this.state.html)}</div>
<button onClick={this.fetchHtml}>Fetch some Html</button>
</div>
);
}
}
I've created a codesandbox here which demonstrates the dangerouslySetInnerHTML
functionality. As mentioned, you want to use dangerouslySetInnerHTML={{ __html: HTML_YOU_WANT_TO_SET }}
to set html. Please use it with caution:
dangerouslySetInnerHTML
is React’s replacement for usinginnerHTML
in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type outdangerouslySetInnerHTML
and pass an object with a__html
key, to remind yourself that it’s dangerous.
const ajaxPlaceholder = () => {
return new Promise(resolve => {
setTimeout(() => resolve("<h1>Test Return</h1>"), 500);
});
};
class App extends React.Component {
constructor() {
super();
this.state = {
html: null
};
this.fetchHtml = this.fetchHtml.bind(this);
}
async fetchHtml() {
const html = await ajaxPlaceholder();
console.log("Got new html!", html);
this.setState({
html
});
}
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
Escaped: <div>{this.state.html}</div>
<br />
Dangerous: <div dangerouslySetInnerHTML={{ __html: this.state.html }} />
<button onClick={this.fetchHtml}>Fetch some Html</button>
</div>
);
}
}
Upvotes: 3