Search Times 미니 프로젝트에 적용한 검색어 하이라이트
검색창에 입력한 키워드와 일치하는 단어를 하이라이트(강조) 하기 위해 split
join
등을 사용할 수 있지만 코드가 다소 복잡해진다. 정규식을 사용하면 깔끔하게 구현할 수 있다.
const getHighlightedText = (text, query) => {
const re = new RegExp(`(${query})`, 'gi');
if (query !== '' && text.match(re)) {
const parts = text.split(re);
return (
<>
{parts.map(part =>
part.toLowerCase() === query.toLowerCase() ? (
<mark key={Math.random().toString(36).slice(2)}>{part}</mark>
) : (
part
),
)}
</>
);
}
return text;
};
return (
// ...생략
<h2>{getHighlightedText(headline, term)}</h2>
)
text
와 query
파라미터를 아래처럼 받았다고 가정해본다. text
문장에 alibaba
라는 문자열(단어)이 들어가 있다면 해당 부분은 모두 하이라이트 처리해야 한다(주황색으로 표시한 부분)
// text 파라미터
'A Chastened Alibaba Tones Down Its Singles alibabaDay Retail Bonanza'
// query 파라미터
'alibaba'
정규식 객체를 생성할 때 변수를 사용하려면 ()
벡틱과 소괄호로 한번 감싼 후 (${변수명})
형태로 입력해준다.
const re = new RegExp(`(${query})`, 'gi'); // /(alibaba)/gi
g
: 전역 검색 플래그. 모든 검색 결과를 배열로 반환. g
플래그가 없으면 최초 검색 결과만 반환.i
: 대소문자 구분 없음 플래그(insensitive). i
플래그가 있으면 대소문자를 구분하지 않음➊query
혹은 text
가 빈 문자열이거나, ➋text
에 매칭되는 query
가 없다면 하이라이팅을 할 필요가 없으므로 이에 대한 조건을 걸어준다.
if (query !== '' && text.match(re)) {
// ...하이라이팅 추가 로직
}
str.match(regexp)
메서드에서 str
이 빈 문자열이거나, 매칭되는게 없으면 null
을 반환한다. gi
플래그를 붙였으므로 대소문자를 구분하지 않고, 찾는 단어가 여러번 등장하면 모든 결과를 배열로 반환한다.