본문 바로가기
  • coingcoing
STUDY/Project

[Project] 검색 기능 (검색하기, Debounce, 검색한 단어에 색 넣기)

by 킵코 2021. 9. 30.

검색기능 추가하기

게시글 목록 페이지에 검색 기능을 추가해보자!

fetchBoards에 있는 search를 가지고 검색을 할 수 있다. 우선 useQuery 해준다.

 

const FETCH_BOARDS = gql`
  query fetchBoards($search:String, $page:Int){
    fetchBoards(search:$search, page:$page){
      _id
      writer
      title
      createdAt
    }
  }
`

const { data, refetch } = useQuery(FETCH_BOARDS)

 

 

querty로 가져온 데이터를 화면에 map으로 보여준다.

 

return (
    <>
      <div>검색 페이지</div>
      {data?.fetchBoards.map((el) => (
        <Wrapper key={el._id}>
          <Colunm>{el.writer}</Colunm>
          <Colunm>{el.title}</Colunm>
          <Colunm>{el.createdAt}</Colunm>
        </Wrapper>
      ))}
    </>
  );

이제 화면에 API로 불러온 글 목록이 뿌려진다. 😀

이제 검색어를 입력할 입력 창과 검색 버튼을 만들어 주고 기능을 추가해 보자.

 

1. input 태그 onChange event가 발생하면 state에 내가 입력한 검색어를 저장한다.

 

const [mySearch,setMySearch] = useState("") // 입력한 검색어 저장하는 state

function onChangeSearch(event) { // 검색어 state에 저장 
	setMySearch(even.target.value)
}


검색어: <input type="text" onChange={onChangeSearch}/> // 검색어를 입력할 input 태그에 onChange
<button>검색</button>

 

2. 버튼을 클릭하면 저장 된 state 값으로 검색 해준다. 

 

function onClickSearch() { //fetchBoard에서 search한 내용을 refetch해주는 함수
  refetch({ search: MySearch })
}

<button onClick={onClickSearch}>검색</button>

 

3. pagination 만들기

 

 

크기가 10인 새로운 배열을 1로 채운다음 map으로 돌려서 1부터 10까지 페이지 번호를 만들어 준다.

{new Array(10).fill(1).map((_,index)=>(
	<span key={uuidv4}>{index + 1}</span>
))}

 

이제 페이지 번호를 클릭하면 검색어에 맞는 화면을 보여주는 함수를 만들어 준다.

 

function onClickPage(event) {
	refetch({search: mySearch, page: Number(event.target.id)})
}


{new Aray(10).fill(1).map((_,index)=>(
	<page key={uuidv4()} onClick={onClickPage} id={String(index+1)}>
    	{index + 1}
    </page>    
))}

이제 페이지 번호를 누르면 화면도 잘 이동한다. 하지만 문제가 있다.

다른 검색어를 입력하고 검색 버튼을 누르지 않아도 바뀐 단어로 페이지가 바뀐다.

onChange가 될 때마다 search state값이 변하기 때문이다.

검색할 단어를 저장해주는  state를 하나 더 만들어 주자.

 

const [myKeyword, setMyKeyword] = useState('') //클릭했을 때 바뀔 검색어 저장하는 state

function onClickSearch() {
 refetch({search: mySearch})
 setMyKeyword(mySearch) // onchange된 값을 search state에 담아준다.
}

function onClickpage(event) {
 refetch({search: myKeyword, page: Number(event.target.id)}) 
}

이제 검색 기능이 잘 실행된다 😘  

 

Debounce 기능

Debounce는 검색버튼을 안눌러도 검색이 바로바로 되는 기능이다.

 

onChange가 바뀔 때 마다 refetch가 되도록 해주면 된다. 

 

function onChangeSearch(event) {
 refetch{search: event.target.value} //onchange 될 때 바로바로 refetch 해준다.
 setMyKeyword(event.target.value)
}

이렇게 해주면 onChange가 발생할 때마다  query를 요청한다. 안돼........🥺

라이브러리를 사용해서 해결해주자 💃 🕺

yarn add lodash

 

lodash를 설치하고 import  해준다.

import _ from 'lodash'

const getDebounce = _.debounce((data)=>{
	refetch({ search: data }) //onChange에서 받은 data로 refetch
    setMyKeyword(data)
},500) //0.5초동안 작동 안하면 실행

function onChangeSearch(event) {
	getDebounce(event.target.value) //onChange data를 getDebounce에 넣어준다.
}

 

검색한 단어 색으로 구분하기 

 

 

내가 검색한 단어가 '킵코'라면 검색한 결과물에서 '킵코' 단어만 다른색으로 구분해 주자. '킵코'

완성 코드를 먼저 보고 정리를 해보자.

 

 {data?.fetchBoards.map((el) => (
        <Wrapper key={el._id}>
          <Colunm>{el.writer}</Colunm>
          <Colunm>
            {el.title
              .replaceAll(myKeyword, `#${myKeyword}#`)
              .split("#")
              .map((el) => (
                <Myword key={uuidv4()} isMatched={myKeyword === el}>
                  {el}
                </Myword>
              ))}
          </Colunm>
          <Colunm>{el.createdAt}</Colunm>
        </Wrapper>

 

1. replaceAll을 사용해서 검색한 단어 찾기

 

.replaceAll(myKeyword, `#${myKeyword}#`)

// 내가 검색한 단어앞뒤로 구분할 수 있는 문자를 넣어준다. 
// replaceAll('킵코', '#킵코#') 해주면 모든 킵코를 찾아서 앞뒤에 ##을 넣어준다.

 

2.  split으로 잘라주고 map으로 돌려서 키워드와 같은 문자 색을 바꿔준다.

 

const Myword = styled.span`
  color: ${(props: Iprops) => (props.isMatched ? "red" : "block")};
`; // 조건으로 글씨색을 바꿔준다.

.split("#")
.map((el) => (
 <Myword key={uuidv4()} isMatched={myKeyword === el}>
  {el}
 </Myword>

 

이제 포트폴리오에 적용해봐야겠다. 🔥 

 

 

 

...keepcoing

'STUDY > Project' 카테고리의 다른 글

[Project] login AccessToken  (0) 2021.10.12
[Project] Image Upload  (0) 2021.09.29

댓글