리액트 텍스트 하이라이트 만들기
요구사항
한 엘리먼트안에서 특정한 키워드를 다른 색싱으로 바꿔서 출력하는 것이다.
아래 예시를 살펴보자
before
1 | <Text>카카오 페이지 카카오 스토리 카카오톡</Text> |
after
1 | <Text> |
의식의 흐름
특정 키워드가 포함되어 있는지, 그리고 그것을 따로 뽑아 낼 수 있는 가장 간단한 방법은 무엇일까? 바로 split 일 것이다.
1 | const splitResult = "카카오 페이지, 카카오 스토리, 카카오톡"; |
그러나 여기서 두 가지 몰랐던 사실을 알게 된다.
- 첫 문자에 seperator 가 동일하게 나올 경우, 앞에 “”가 무조건 나온다.
- text === seperator 면 결과는 빈 문자열 두개다.
1 | const splitResult = "카카오"; |
문자열에서 separator가 등장하면 해당 부분은 삭제되고 남은 문자열이 배열로 반환됩니다. separator가 등장하지 않거나 생략되었을 경우 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우, str은 문자열의 모든 문자를 원소로 가지는 배열로 변환됩니다. separator가 원본 문자열의 처음이나 끝에 등장할 경우 반환되는 배열도 빈 문자열로 시작하거나 끝납니다. 그러므로 원본 문자열에 separator 하나만이 포함되어 있을 경우 빈 문자열 두 개를 원소로 가지는 배열이 반환됩니다.
평소에 잘 몰랐던 split의 심오한 철학이 많이 있으니 가서 확인해보는 것도 좋을 듯 하다.
암튼 첫 번쨰 결과물은 이렇다.
1 | const [initial, ...rest] = text.split(highlight) |
reduce 를 활용해서, 처리했다.
근데 어차피, map으로 돌면서 하는게 더 간단하지 않을까 하는 아이디어가 나왔다.
결과
1 | const initial = text.split(highlight) |
i > 0
을 처리한 이유는, 어차피 첫번째 엘리먼트는 무조건 하이라이트가 안되는 텍스트가 오기 때문이다! 첫단어가 일치하는 단어라면 “”가 올 것이고, 일치 하지 않는 단어라면 그 단어 그대로 올라오기 떄문에 첫번째 단어는 별도처리를 하지 않아도 된다.
그리고 두번째 엘리먼트 부터 해당 text가 있어서 쪼개진 단어가 올것이기 때문에, 앞에 하이라이트 텍스트를 붙여주고, 그 다음 평범한 단어를 붙여주면 된다.