0

I am using React and I try to highlight the value typed by the user in a string containing this value.

In order to highlight this value, I am trying to replace the substring corresponding to this.props.value with a substring containing this value + html.

For example, for the item.name : John If the user types "Jo". I want to display John The substring "Jo" is highlighted.

This is my code:

{this.props.value.length > 0 &&
    item.name.search(this.props.value)
    ? item.name.replace(this.props.value, `<span className="myClass">${this.props.value}</span>`)
    : item.name
}

The value returned is plain text, the span is not taken as html. How can I make this html tags interpreted?

Rosen Dimov
  • 1,055
  • 12
  • 32
Aurélien
  • 1,617
  • 1
  • 21
  • 33

3 Answers3

0

Here I am not focusing on your code.

I just tell how you can highlight your text through react logics. if You have value in your item.name then how to highlight text and if not then what to do.

 <div>
        {item.name && <span className="myClass">${this.props.value}</span>}
        {!item.name && this.props.value}
 </div>
Sourav Singh
  • 878
  • 1
  • 8
  • 14
  • If `this.props.value`is empty this code provides a single `$`. If I remove the `$`because it this case we do not need interpolation, the `item.name` is completely replaced by `this.props.value`. – Aurélien Aug 01 '20 at 17:25
0

You can use this:

const handleMatch = () => {
    return (
      <span>
        <span style={{ color: "red" }}>{props.value}</span>
        <span>{item.name.replace(props.value, "")}</span>
      </span>
    );
  };

  return (
    <div>
      {props.value.length > 0 && item.name.search(props.value) === 0
        ? handleMatch()
        : item.name}
    </div>
  );
};

Here is a working demo

Nicolas Hevia
  • 15,143
  • 4
  • 22
  • 31
0

For the most robust solution in your case, this can do the work, but you should be very aware of what it is all about! It doesn't contain dangerously in its name for no reason:

In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack.

If you go with this solution, you must be 100% sure that the value coming from the user's input is validated and proven to be safe (at the very least, be html-escaped).


And if you want the safer solution (RECOMMENDED), you'll need to write a bit more code, check this codesandbox (excuses if I have missed some index validation, but you'll get the point). As you see, it iterates over the string checking the index where the match starts, takes the piece of text before the match (without styling it) and after that puts the styled phrase. From there it continues to the end to find all remaining matches. It can get more complex if your string itself, for example, can contain html, in which case you'll be tokenizing the string even further.

Rosen Dimov
  • 1,055
  • 12
  • 32
  • I also thought he wanted to use dangerouslySetInnerHTML at first, but he actually wanted to highlight a matched phrase. Check my solution – Nicolas Hevia Aug 01 '20 at 18:00
  • He still needs to output the result as html, and also the phrase might repeat several times in the target text. OP hasn't stated length and complexity of text. – Rosen Dimov Aug 01 '20 at 18:31
  • I also added string-tokenization solution, which doesn't use dangerouslySetInnerHTML. – Rosen Dimov Aug 01 '20 at 19:19