Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sanitize HTML String without using dangerouslySetInnerHTML for length check

Can I sanitize string without using dangerouslySetInnerHTML in React JSX. Requirement is to check the length of sanitized html string and then only include the component. Something like

    var SomeComponent = React.createClass({
       render:function(){
         return (
            {this.props.htmlString.length > 0 ? <Child htmlString={this.props.htmlString} : null}
         )
       }
    })

var Child = React.createClass({
    render:function(){
      return (
        <p dangerouslySetInnerHTML={{__html: this.props.htmlString}}></p>
      )
    }
})

Everything works fine but fails when this.props.htmlString='&nbsp' . In this case length > 0 and component gets included. So I want to check the length of innerHTML before the element inclusion itself.

One Possible Solution I came across is something like :

var html = "&nbsp;";
var div = document.createElement('div');
div.innerHTML = html; //check the length of innerHTML now

But I am looking for a cleaner one more of react type.

like image 589
Ankur Aggarwal Avatar asked Oct 31 '22 11:10

Ankur Aggarwal


1 Answers

As you already suggested, resolving a HTML string into plain text is easily done by filling a DOM element with it.

function htmlToText(htmlString) {
  const el = document.createElement('div');
  el.innerHTML = htmlString;
  return el.textContent;
}

This turns your markup into plaintext:

htmlToText('&nbsp;') === '\xa0'  // non-breaking space character

Checking that the resolved text isn't empty is then trivial:

htmlToText('&nbsp;').trim().length === 0
htmlToText('&nbsp; FOO ').trim().length === 3

There's no "React way" to do this, because if you're setting HTML directly from string, it's only resolved when actually injected into the DOM. Of course you could use this tool to create a HOC:

const nonEmptyHtml = Component => props => {
  const html = props.dangerouslySetInnerHTML;
  if (html && !htmlToText(html).trim().length) {
    return null;
  }
  return <Component {...props} />;
};

Usage:

const NonEmptyParagraph = nonEmptyHtml('p');
ReactDOM.render(<NonEmptyParagraph dangerouslySetInnerHTML={htmlString} />);
like image 165
hon2a Avatar answered Nov 12 '22 17:11

hon2a