Skip to content Skip to sidebar Skip to footer

Highlight Text Using Reactjs

I'm trying to highlight text matching the query but I can't figure out how to get the tags to display as HTML instead of text. var Component = React.createClass({ _highlig

Solution 1:

Here is my simple twoliner helper method:

getHighlightedText(text, highlight) {
    // Split text on highlight term, include term itself into parts, ignore case
    const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
    return <span>{parts.map(part => part.toLowerCase() === highlight.toLowerCase() ? <b>{part}</b> : part)}</span>;
}

It returns a span, where the requested parts are highlighted with <b> </b> tags. This can be simply modified to use another tag if needed.

UPDATE: To avoid unique key missing warning, here is a solution based on spans and setting fontWeight style for matching parts:

getHighlightedText(text, highlight) {
    // Split on highlight term and include term into parts, ignore case
    const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
    return <span> { parts.map((part, i) => 
        <span key={i} style={part.toLowerCase() === highlight.toLowerCase() ? { fontWeight: 'bold' } : {} }>
            { part }
        </span>)
    } </span>;
}

Solution 2:

Here is an example of a react component that uses the standard <mark> tag to highlight a text:

const Highlighted = ({text = '', highlight = ''}) => {
   if (!highlight.trim()) {
     return <span>{text}</span>
   }
   const regex = new RegExp(`(${_.escapeRegExp(highlight)})`, 'gi')
   const parts = text.split(regex)
   return (
     <span>
        {parts.filter(part => part).map((part, i) => (
            regex.test(part) ? <mark key={i}>{part}</mark> : <span key={i}>{part}</span>
        ))}
    </span>
   )
}

And here is how to use it

<Highlighted text="the quick brown fox jumps over the lazy dog" highlight="fox"/>

Solution 3:

There is already a react component on NPM to do what you want:

var Highlight = require('react-highlighter');
[...]
<Highlight search={regex}>{name}</Highlight>

Solution 4:

Here's my solution.

I tried to focus on simplicity and performance, so I avoided solutions that involved manual manipulation of the DOM outside of React, or unsafe methods like dangerouslySetInnerHTML.

Additionally, this solution takes care of combining subsequent matches into a single <span/>, thus avoiding having redundant spans.

const Highlighter = ({children, highlight}) => {
  if (!highlight) return children;
  const regexp = new RegExp(highlight, 'g');
  const matches = children.match(regexp);
  console.log(matches, parts);
  var parts = children.split(new RegExp(`${highlight.replace()}`, 'g'));

  for (var i = 0; i < parts.length; i++) {
    if (i !== parts.length - 1) {
      let match = matches[i];
      // While the next part is an empty string, merge the corresponding match with the current
      // match into a single <span/> to avoid consequent spans with nothing between them.
      while(parts[i + 1] === '') {
        match += matches[++i];
      }

      parts[i] = (
        <React.Fragment key={i}>
          {parts[i]}<span className="highlighted">{match}</span>
        </React.Fragment>
      );
    }
  }
  return <div className="highlighter">{parts}</div>;
};

Usage:

<Highlighter highlight='text'>Some text to be highlighted</Highlighter>

Check out this codepen for a live example.


Solution 5:

By default ReactJS escapes HTML to prevent XSS. If you do wish to set HTML you need to use the special attribute dangerouslySetInnerHTML. Try the following code:

render: function() {
        var name = "Javascript";
        var query = "java"
        return (
            <div>
                <input type="checkbox" /> <span dangerouslySetInnerHTML={{__html: this._highlightQuery(name, query)}}></span>
            </div>
        );
    }

Post a Comment for "Highlight Text Using Reactjs"