자동 검색 기능 구현하기: lodash debounce
2023. 2. 10. 11:38ㆍNext.js
728x90
반응형
검색 하기 버튼을 누르지 않아도 자동으로 검색이 되도록 하려면,
검색창의 onChange
함수가 실행될 때 refetch
가 일어나면 된다.
하나하나 입력할 때마다 refetch가 일어나면 무수히 많은 요청이 가서 서버에 부하를 줄 수 있으므로, debouncing을 이용해서 일정 기간 텀을 두고 요청을 보내게 만든다.
자동 검색 구현하기
1. lodash 설치
yarn add lodash
yarn add '@types/lodash' --dev
2. import
import _ from 'lodash'
3. lodash의 debounce 사용
const getDebounce = _.debounce((data) => {
// data: event.target.value
// 0.2초 동안 재작업이 없으면 실행되는 부분
setKeyword(data);
refetch({ search: data, page: 1 }); // 바로 실행되지 않고, 0.2초 동안 재입력이 일어나지 않으면 그 때 리페치가 실행된다.
}, 200); // 0.2초
const onChangeSearch = (event: ChangeEvent<HTMLInputElement>) => {
getDebounce(event.target.value);
};
검색한 부분 스타일 주기
원리
전체 문자열을 단어 단위로 쪼개놓고 span 태그로 만들어준다.
검색된 태그에만 스타일을 준다.
1. keyword 스테이트를 만들고, 검색한 단어를 저장한다.
const [keyword, setKeyword] = useState("");
const getDebounce = _.debounce((data) => {
setKeyword(data);
}, 200);
2. 문자열 split
- 검색어를 시크릿 코드를 감싼 문자열로 바꾸고(replaceAll),
- 시크릿 코드를 기준으로 문자열을 나눈다.(split)
{el.title .replaceAll(keyword, `#$%${keyword}#$%`) .split("#$%") .map((el) => ( <Word key={uuidv4()} isMatched={keyword === el}> {el} </Word> ))}
3. isMatched가 true일 경우에 스타일 지정
interface IProps {
isMatched: boolean;
}
const Word = styled.span`
color: ${(props: IProps) => (props.isMatched ? "red" : "black")};
`;
전체 코드
import { useQuery, gql } from "@apollo/client";
import styled from "@emotion/styled";
import { ChangeEvent, useState } from "react";
import {
IQuery,
IQueryFetchBoardsArgs,
} from "../../src/commons/types/generated/types";
import _ from "lodash";
import { v4 as uuidv4 } from "uuid";
import * as S from "./day20.style";
const FETCH_BOARDS = gql`
query fetchBoards($search: String, $page: Int) {
fetchBoards(search: $search, page: $page) {
_id
writer
title
contents
}
}
`;
export default function MapBoardPage() {
const [keyword, setKeyword] = useState("");
const { data, refetch } = useQuery<
Pick<IQuery, "fetchBoards">,
IQueryFetchBoardsArgs
>(FETCH_BOARDS);
const getDebounce = _.debounce((data) => {
// data: event.target.value
// 0.2초 동안 재작업이 없으면 실행되는 부분
setKeyword(data);
refetch({ search: data, page: 1 }); // 바로 실행되지 않고, 0.2초 동안 재입력이 일어나지 않으면 그 때 리페치가 실행된다.
}, 200);
const onChangeSearch = (event: ChangeEvent<HTMLInputElement>) => {
getDebounce(event.target.value);
};
const onClickPage = (e: any) => {
refetch({ page: Number(e.target.id) });
};
return (
<>
<S.Wrapper>
<S.SearchWrapper>
검색어 입력
<S.Search type="text" onChange={onChangeSearch} />
</S.SearchWrapper>
{data?.fetchBoards.map(
(
el // 인자로 index를 써서 사용할 수 있음: 순서, 필요 없으면 안 써도 됨
) => (
<S.Row key={el._id}>
<S.Title>
{el.title
.replaceAll(keyword, `#$%${keyword}#$%`)
.split("#$%")
.map((el) => (
<S.Word key={uuidv4()} isMatched={keyword === el}>
{el}
</S.Word>
))}
</S.Title>
<S.Writer>{el.writer}</S.Writer>
</S.Row>
)
)}
<S.PageWrapper>
{new Array(10).fill(1).map((_, index) => (
<S.Page
onClick={onClickPage}
id={String(index + 1)}
key={index + 1}
>
{index + 1}
</S.Page>
))}
</S.PageWrapper>
</S.Wrapper>
</>
);
}
728x90
반응형
'Next.js' 카테고리의 다른 글
Next.js와 브라우저 저장소 (4) | 2023.07.14 |
---|---|
[Firebase] 프론트엔드에서 DB 다루기 (1) | 2023.02.03 |
[react-infinite-scroller] 무한스크롤 적용하기 (0) | 2023.02.02 |