DoneDeal0
DoneDeal0

Reputation: 6257

How to inject data in a html string in React?

I have a html string that contains a link. I need to add the attribute rel="noopener" for security purposes. The html string is injected through dangerouslySetInnerHtml:

const Component = ({ message }) => {
  return (
    <div>
      <div dangerouslySetInnerHTML={{ __html: message }} />
    <div>
  );
};

The string looks like: Hello check out <a href="https://my-link.com" target="_blank">this page</a>

So the desired output would be: Hello check out <a href="https://my-link.com" target="_blank" rel="noopener">this page</a>

How to do it?

Upvotes: 0

Views: 439

Answers (4)

Tan S&#228;&#228;lik
Tan S&#228;&#228;lik

Reputation: 76

Maybe consider using a function or component that puts it all together based on the data you send in? E.g.

function App() {
  const linkBuilder = (textBefore, linkText, textAfter, href) => {
    return (
      <div>
        {textBefore}
        <a href={href} target="_blank">
          {linkText}
        </a>
        {textAfter}
      </div>
    );
  };
  return (
    <div>
      {linkBuilder("Hello check out ", "this page", "", "www.google.com")}
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Also according to this you don't need rel=noopener anymore if you use target="_blank". But if it's necessary you can pass it in as a boolean and apply it on the function/component side.

Upvotes: 0

Mal
Mal

Reputation: 385

Try this:

const Component = ({ message }) => {

    function secureATags(html) {
        // Parse HTML
        let doc = (new DOMParser()).parseFromString(html, "text/html")
        // Append attribute
        doc.querySelectorAll('a').forEach(entry => {
            entry.setAttribute('rel', 'noopener')
        })

        // Reserialize to HTML
        return doc.body.innerHTML
    }

    return (
        <div>
            <div dangerouslySetInnerHTML={{ __html: secureATags(message) }} />
        <div>
    )
}

Upvotes: 2

kunal panchal
kunal panchal

Reputation: 798

Direct use of setDangerousInnerHtml is strictly not recommended due to security issues. you can use a plugin on npmjs.org pkgname: React-html-parser for injecting the html safely

Upvotes: 0

Peter B
Peter B

Reputation: 24136

I would use the Browser DOM to achieve this, as follows:

const div = document.createElement("div");

div.innerHTML = 'Hello check out <a href="https://my-link.com" target="_blank">this page</a>';
div.childNodes[1].setAttribute("rel", "noopener");

console.log(div.innerHTML);

If the actual HTML text is more complex than in your example, then div.childNodes[1] will need to be replaced with code that looks for and selects the proper node. But even then (or especially then?), this is probably the easiest and most reliable way to achieve your goal.

Upvotes: 0

Related Questions