ㅇㅇㅈ Blog

프론트엔드 수행중

0%

2022-06-12-TIL

검색 요청 최적화

input에 타이핑을 칠때마다 리렌더링이 되면서 데이터요청이 된다..

조건문과 setTimeout으로 인풋에 입력이 끝나면 데이터요청을 하도록 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const App: FC = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [news, setNews] = useState<News[]>([]);
const [hasMore, setHasMore] = useState(false);
const [search, setSearch] = useState('');
const [page, setPage] = useState(0);

// 데이터 요청
const getData = (query: string, page: number) => {
setLoading(true);
setError(false);

axios({
method: 'GET',
url: `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}`,
params: { q: query, page },
})
.then((res) => {
// console.log(res.data.response.docs);
setNews((prevNews) => {
return [...new Set([...prevNews, ...res.data.response.docs])];
});
setHasMore(res.data.response.docs.length > 0);
setLoading(false);
})
.catch((e) => {
if (axios.isCancel(e)) return;
setError(true);
});
};
useEffect(() => {
setNews([]);
}, [search]);

useEffect(() => {
if (search !== '') {
if (!loading) {
const timer = setTimeout(() => {
getData(search, page);
setPage(1);
}, 1500);
return () => {
clearTimeout(timer);
};
}
}
}, [search, page]);

먼저 데이터요청 함수 getData를 작성해주고
useEffect 안에서 함수를 호출 한다.

1
2
3
useEffect(()=>{
getData(search,page)
},[search,page])

이렇게 작성하고 나면 문제점

  1. 돔이 마운트 될때 useEffect가 한번 실행되면서 검색어를 쓰지 않아도 검색이 시작된다는 점.
  2. setSearch로 인풋에서 value를 받아올때마다 리렌더링이 되면서 타이핑 갯수만큼 검색요청이 일어난다는 점.

조건문과 setTimeout으로 해결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
useEffect(()=>{
if(search !== '') {
// search가 비어있지 않으면 요청 시작
if(!loading) {
// loading이 false이면 요청 시작
const Timer = setTimeout(()=>{
// setTimeout으로 1.5초 후에 getData() 호출
getData(search,page)
},1500)
}
return ()=>{
// cleanUp 으로 clearTimeout
// cleanUp 을 안해주면 그냥 1.5초후에 타이핑 갯수만큼 요청이 일어난다
clearTimeout(timer)
}
}
},[search,page])