Search code examples
javascriptreactjsdjangosearchmarkdown

Highlight words in markdown content according to search result using Reactjs


I am building React/Django app that is using markdown content I want to put a search bar at which the user can search in the blog content and the words that are matching the search results are highlighted.

I have used react-highlight-words library but I found that It isn't compatible with markdown content so I am trying using react-string-replace library but there is a problem that faced me in the test

react-string-replace returns array not string so I tried to use a hook (useState) which is an empty string and map each word in the array and append it to the hook then put the Hook inside ReactMarkdown element.

import React from 'react'
import ReactMarkdown from 'react-markdown'
import reactStringReplace from 'react-string-replace';
export default function Mark(){
   
   
    const [stringData, setStringData] = React.useState("");
    
    const content = 'Hey my number is 555-555-5555.';
   const replacearray= reactStringReplace(content, 's', (match, i) => (
        `===${match}===`
      ));
console.log(replacearray)
replacearray.map(word =>{
    console.log(word)
    setStringData(stringData + `${word}`)


})
console.log(stringData)
    return(
       <ReactMarkdown>{stringData}</ReactMarkdown>
    )
}

The result of console.log(replacearray) is:

  Array(3) [ "Hey my number i", "===s===", " 555-555-5555." ]

The result of console.log(word) is:

Hey my number i        mark.js:116:13
===s===                mark.js:116:13
 555-555-5555          mark.js:116:13

The result of console.log(stringData) is:

 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555. 555-555-5555.

so how the result of stringData is like this although the result of each word is the word itself?


Solution

  • You're not using the current value from the state but the last value. This has something to do with how React handles state changes. Here you start with a empty string "" and you end up with 555-555-555 since that is the last value of the replacearray.

    The reason you see so many times the 555-555-555 is probably due to caching it will be just 555-555-555 when you do a hard refresh.

    export default function Mark() {
      const [stringData, setStringData] = React.useState("");
    
      replacearray.map((word) => {
        console.log(word);
        setStringData(stringData + `${word}`);
      });
    }
    

    Instead what you want to use if you set the state inside of a loop is the callback function provided by the setState function. This will return the current / most up to date value.

    replacearray.map((word) => {
      console.log(word);
      setStringData((prevStringData) => {
        return prevStringData + word;
      });
    });
    

    Or you could even use the .join() method.

    setStringData(replacearray.join(""));