검색기능 추가하기
게시글 목록 페이지에 검색 기능을 추가해보자!
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 |
댓글