Reputation: 2554
I have a page built with React (NextJS) and I am pulling some markup string content from Wordpress and inserting it into my JSX
, like so:
...
<div className="wrapper">
<p
className="text-content"
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
></p>
</div>
...
Now, the markup possibly contains links and I want to open all those links on new tab. So I tried:
...
<div className="wrapper">
<base target="_blank" />
<p
className="text-content"
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
></p>
</div>
...
and all links in the markup are opened on new tab so, great. But the problem is that all other links in the page including those outside the div.wrapper
element are opened in new tabs (since <base />
is scoped to the entire page) and I'll like to prevent this.
Since I can't use multiple <base />
on the same page, the other option I'm aware of is to loop through anchor tags of interest with document.querySelector(".wrapper a")
and add the target
attribute to all of them but, in React it's an anti-pattern to modify the DOM directly.
So I'm not sure how best to proceed. What do I do?
Upvotes: 3
Views: 1262
Reputation: 8064
Well first of all base element should only be inserted in html head element, and not inside the body html element, you could do that imperatively or using the react-helmet library - if you still need to use it.
dangerouslySetInnerHTML is in itself an imperative pice of code, but sometimes its the only possible solutions for a certain use cases, now regarding the links you could either do it using imperative code in a useEffect
or componentDidMount
, or you code use react-html-parser which will enable you to modify dom elements in a more declarative fashion - i say in a more declarative fashion because while its a react component in practice its still more imperative than its declarative in nature, but still better than custom code running in useEffect
or componentDidMount
Upvotes: 1
Reputation: 427
You can use DOMParser API to achieve that.
Here's a little snippet
const parser = new DOMParser();
const htmlText = `<div><a href="#some-url">Url link</a></div>`;
let content = parser.parseFromString(htmlText, "text/html");
const anchors = content.getElementsByTagName('a');
Array.from(anchors).forEach(a => {
a.setAttribute("target", "_blank");
})
console.log(content.body.innerHTML); // Here it is your new string
The code may need to be improved a bit, I've just typed this out of MDN example and I didn't have time to test it. Does this work?
Upvotes: 6