Search code examples
reactjssearchhighlightindexof

Highlight search term using the indexOf in React


I have a search component that returns data from slideData based on the searchTerm. My goal is to highlight the word that is typed. I think i need to use indexOf or tag but I am struggling with the logic of where to use it? For clarity, the expected result is that if i search for "hamburger" it will display all results with hamburger and highlight "hamburger" in those results.

const [searchTerm, setSearchTerm] = useState("");
const SlideData = [
  {
    slideIndex: 1,
    title: "My name is Bob",
    text1: "Bob likes to eat hamburgers",
    text2: "Kenny likes to eat hot dogs",
    text3: "Terry likes milkshakes"
  },
  {
    slideIndex: 2,
    title: "My name is Jill",
    text1: "Jill likes to eat hamburgers",
    text2: "Joshua likes to eat hot dogs",
    text3: "Steven likes milkshakes"
  }
]
<div className="search-results">
          <ul className="search-list">
            {SlideData.filter((item) => {
              if (searchTerm === "") {
                return null;
              } else {
                //concat the text properties into variable//
                let searchText = item.title + item.text1 + item.text2 + item.text3 + item.text4;
                //if the variable contains the search term value//
                if (searchText.toLowerCase().includes(searchTerm.toLowerCase())) {
                  //return those items//
                  return item;
                }
              }
          
            }).map((item) => (
              //map through the items and display list of results
              <div key={item.slideIndex} style={{ marginTop: "20px" }}>
                <h4 style={{ color: "white" }}>{item.title}</h4>
                <li className="search-item">{item.text1}</li>
                <li className="search-item">{item.text1.indexOf(searchTerm)}</li>
                <a
                  className="search-link"
                  onClick={() => {
                    context.setCurrentSlide(item.slideIndex);
                    setSearchTerm("");
                  }}
                >
                  Go To Slide {item.slideIndex}
                </a>
              </div>
            ))}
          </ul>
        </div>

SOMETHING I AM TRYING



        //find the search term in the results//
              const highlighted = item.text1.indexOf(searchTerm);
              if(searchTerm === -1){
                //highlight the term
              }else{
                //Do nothing
              }

Solution

  • In order to target the results with different styles you need to break it out to it's own HTML element.

    You can use this regex function

    const splitResult = (result) =>
    //Split on search result and then simply style the matches
    result.split(new RegExp(`(${searchTerm})`, `gi`)).map((piece, index) => {
      return (
        <span
          key={index}
          style={{
            background:
              piece.toLowerCase() === searchTerm.toLocaleLowerCase()
                ? "YELLOW"
                : "TRANSPARENT"
          }}
        >
          {piece}
        </span>
      );
    });
    

    Here's your full component I removed some parts that are not related to the question

    export default function App() {
      const [searchTerm, setSearchTerm] = useState("");
    
      const splitResult = (result) =>
        //Split on search result and then simply style the matches then map through
        result.split(new RegExp(`(${searchTerm})`, `gi`)).map((piece, index) => {
          return (
            <span
              key={index}
              style={{
                background:
                  piece.toLowerCase() === searchTerm.toLocaleLowerCase()
                    ? "YELLOW"
                    : "TRANSPARENT"
              }}
            >
              {piece}
            </span>
           );
         });
    
       return (
         <div className="search-results">
           <ul className="search-list">
             {/** Search input */}
             <input
               type="search"
               value={searchTerm}
               onChange={(e) => setSearchTerm(e.target.value)}
             />
             {SlideData.filter((item) => {
               if (searchTerm === "") {
                 return null;
               } else {
                //concat the text properties into variable//
                 let searchText = item.title + item.text1 + item.text2 + item.text3 + item.text4;
                //if the variable contains the search term value//
                if (searchText.toLowerCase().includes(searchTerm.toLowerCase())) {
                   //return those items//
                   return item;
                }
              }
              return null;
             }).map((item) => (
              //map through the items and display list of results
              <div key={item.slideIndex} style={{ marginTop: "20px" }}>
                <h4>{item.title}</h4>
                <li>{splitResult(item.text1)}</li>
                <li>{item.text1.indexOf(searchTerm)}</li>
              </div>
            ))}
          </ul>
        </div>
      );
    }