ReactJS - <Linkify> and <Highlighter> components don't work together

1.7k Views Asked by At

In my current assignment in ReactJS, I was requested to render a string which contains url addresses, so those urls' will be clickable links and the text will be highlighted by search words.

Thus, I made a component which imported "react-linkify" and "react-highlight-words" components.

If I use component on its own, then the url addresses will be converted to clickable links. So for the component as its own that the text will be highlighted by search word as expected.

When I used both of them, the component functionality works but the component doesn't render the urls to links.

I've tried every solution I could search in Google, even making my own linkify using Regular Expressions but then the links still stays as a string and not rendered as clickable links.

My code from the CodeSandBox.io:

import React from "react";
import ReactDOM from "react-dom";
import Linkify from "react-linkify";
import Highlighter from "react-highlight-words";

import "./styles.css";

function App() {
  let text =
    "Hello CodeSandbox. Start editing to see some magic happen! Click to see this video: https://www.youtube.com/watch?v=VMcPWuQ7IeE ";

  return (
    <div className="App">
      <Linkify>
        <Highlighter
          highlightClassName="YourHighlightClass"
          searchWords={["magic", "video"]}
          autoEscape={true}
          textToHighlight={text}
        />
      </Linkify>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I'm a new in React and I'll be thankful if you can help me on this issue.

1

There are 1 best solutions below

0
user12649626 On

You can improve it, but I just managed to make something work this way: 1. Add "http" in Highlighter's searchWords array. 2. Use findChunks to select complete words from start to next space character. So for example any url like 'https://codesandbox.io/s/k20x3ox31o' become fully highlighted. 3. Use a custom highlightTag to wrap highlighted words in Linkify.

const findChunks = ({
    autoEscape,
    caseSensitive,
    sanitize,
    searchWords,
    textToHighlight
  }) => {
    const chunks = [];
    const textLow = textToHighlight.toLowerCase();
    const sep = /[\s]+/;

    const singleTextWords = textLow.split(sep);

    let fromIndex = 0;
    const singleTextWordsWithPos = singleTextWords.map(s => {
      const indexInWord = textLow.indexOf(s, fromIndex);
      fromIndex = indexInWord;
      return {
        word: s,
        index: indexInWord
      };
    });

    searchWords.forEach(sw => {
      const swLow = sw.toLowerCase();
      singleTextWordsWithPos.forEach(s => {
        if (s.word.includes(swLow)) {
          const start = s.index;
          const end = s.index + s.word.length;
          chunks.push({
            start,
            end
          });
        }
      });
    });

    return chunks;
  };

/******************************************************/

<Highlighter
  highlightClassName="YourHighlightClass"
  textToHighlight={message.text}
  searchWords={['http']}
  autoEscape={true}
  findChunks={findChunks}
  highlightTag={({ children, highlightIndex }) => (
    <Linkify><span style={{backgroundColor: 'crimson', color: 'white'}}>{children}</span></Linkify>
)}/>