반응형
✔️ 필요성
검색어를 API에 호출해서 결과를 가져오고 싶다. 그런데 검색어를 한글자씩 바꿀때마다 API를 계속 호출하는 것은 원하지 않는다. 어느정도 글자가 정지했을 때 한 번만 API 호출하고 싶다.
debounce와 useMemo를 활용해서 아래와 같이 searchText를 변경한다.
검색창에 등장하는 단어인 query는 debounce를 적용하지 않아서 변경 즉시 값이 바뀌도록하고, searchText는 debounce를 적용한다.
import React, { useEffect, useRef, useState, useMemo } from "react";
import { debounce } from "lodash";
const DEBOUNCE_TIME = 500;
const SearchInput = ({
placeholder,
searchText,
setSearchText,
selectedItem,
setSelectedItem,
options,
className,
}: Props) => {
const [query, setQuery] = useState<string>(searchText); // 검색텍스트(즉각)
/* 눈에보이는 query text는 즉각 변화 */
const onChangeText = (query: string) => {
setQuery(query);
};
/* 0.5초 debounce로 검색 API 호출 */
const debouncedSearch = useMemo(
() =>
debounce((query: string) => {
query.length > 0 && setSearchText(query); // 빈칸일 때는 검색하지 않는다
}, DEBOUNCE_TIME),
[searchText]
);
return (
<Input
type="text"
value={query}
onChange={(e) => {
debouncedSearch(e.target.value);
onChangeText(e.target.value);
}}
/>
);
};
export default SearchInput;
✔️ 문제 확인
searchText가 바뀌면 데이터를 호출한다. 데이터를 호출하는 부분과 데이터를 보여주는 부분은 컴포넌트를 분리하는 것이 깔끔하다.
const [searchText, setSearchText] = useState<string>(''); // 검색 API에 호출하는 단어
/* 데이터 호출 */
const { options, error: optionsError } = useOptionsQuery(searchText);
return (
<SearchInput
options={optionsError ? [] : options} // 옵션값이 없으면 빈칸을 내려보낸다
searchText={searchText}
setSearchText={setSearchText}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
useSWR이 써본 것 중에서 제일 깔끔한 것 같다.
import axios from "axios";
import useSWR from "swr";
export const useOptionsQuery = (searchText: string) => {
const fetcher = (url: string) =>
axios.get(encodeURI(url)).then((res) => res.data);
// API주소에 검색어를 넣어서 호출
const key = `api주소?search=${searchText}`;
const { data, error } = useSWR(key, fetcher);
return { data, error };
};
반응형
'프론트엔드 웹 > React' 카테고리의 다른 글
Module not found: Error: You attempted to import /node_modules/react-refresh/runtime.js which falls outside of the project src/ directory (1) | 2022.08.31 |
---|---|
Promise.all map으로 병렬로 요청하기 (0) | 2022.08.31 |
Axios Error code/status 처리하기 (0) | 2022.07.06 |
이메일(e-mail)로 연결하는 a tag (0) | 2022.06.28 |
REACT 웹에서 S3로 이미지 올리기 (3) _ React code (0) | 2022.06.21 |