일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- javascript
- 안드로이드
- typescript
- Python
- 스택
- 백준 스택 시간초과 python
- firebase
- 자바스크립트
- Android
- CSS
- next Link
- stdin vs input
- NPM
- k for k
- C++
- react
- 최적화
- 알고리즘
- 타입스크립트
- 파이어베이스
- kotlin
- 리액트
- 프론트엔드
- JS
- 파이썬
- 코딩테스트
- nodejs
- HTML
- TS
- 백준 스택
- Today
- Total
sooleeandtomas
Infinity Scroll (Debounce & Throttle 어떤걸 쓰면 좋을까?) 본문
Debounce & Throttle
엄청나게 많은 양의 이벤트가 일어났을 때 콜백의 수를 줄여줍니다.
온체인지가 일어날 떄 실행되는 콜백의 실행을 효과적으로 줄여줍니다.
debounce :
마지막 이벤트로부터 일정 시간을 기다렸다가 이벤트를 수행합니다.
일정시간 내에 같은 이벤트가 또 들어오면 이전 요청은 취소합니다.
[연관검색어, .. ]
throttle :
일정 시간 동안 일어난 이벤트를 모아서 주기적으로 1번 실행해줍니다.
일정 시간 동안 가장 최근의 이벤트를 실행해줍니다.
[스크롤 이벤트 .. ]
디바운스와 트로틀을 제공해주는 Lodash를 이용합니다.
import React from "react";
import _ from "lodash";
const Search = () => {
const debounce = _.debounce((e)=>{
console.log(e.target.value)
}, 2000)
const throttle = _.throttle((e)=>{
console.log(e.target.value)
}, 2000)
const onChange = e => {
console.log(e.target.value)
}
return(
<div>
<input type="text" onChange={throttle}/>
</div>
)
}
export default Search;
주의 ! 함수형 컴포넌트에서 state가 업데이트되면 그 안에 함수들이 모두 업데이트 됩니다.
그래서 debounce가 제대로 작동하지 않습니다.
이를 위해 useCallback을 사용합니다.
함수가 리랜더링 되더라도 debounce는 리랜더링 되지 않도록 해줍니다.
import React, { useCallback, useState } from "react";
import _ from "lodash";
const Search = () => {
const [text, setText] = useState("");
const debounce = _.debounce((e)=>{
console.log(e.target.value)
}, 2000)
const keyPress = useCallback(debounce, []); // 함수는 리랜더링이 되더라도 debounce는 초기화 되지 않습니다.
const throttle = _.throttle((e)=>{
console.log(e.target.value)
}, 2000)
const onChange = e => {
setText(e.target.value);
keyPress(e);
}
return(
<div>
<input type="text" onChange={onChange} value={text}/>
</div>
)
}
export default Search;
예제 : 스크롤 이벤트
함수형 컴포넌트에서 이벤트 종료시키는 법 : useEffect에서 return () => { ... }
useEffect(()=>{
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll)
},[])
window.innerHeight : 모니터 높이 // 메뉴바, 툴바 제외
document.body.scrollHeight : 도큐먼트 전체의 높이 //눈에 안보이는 높이 포함
document.scrollTop : 스크롤이 얼마나 움직였는지
const { innerHeight } = window; // 모니터 창
const { scrollHeight } = document.body; // 도큐먼트 전체 창
const scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
//얼마나 스크롤 했는지
scrollHeight - innerHeight - scrollTop = 스크롤하고 남은 창
if(scrollHeight - innerHeight - scrollTop < 200){
callNext();
}
위에서도 말했듯이 함수형 컴포넌트에서는 리랜더링될때마다 debounce, throttle 도 리랜더링 되기 때문에
이 함수들은 useCallback을 사용해서 따로 기억해줘야 합니다.
const handleScroll = useCallback(_handleScroll, [is_loading]);
_handleScroll을 기억해준 것을 handleScroll이라고 합니다.
const _handleScroll = _.throttle(()=>{
if(is_loading){return}
const { innerHeight } = window;
const { scrollHeight } = document.body;
const scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
if(scrollHeight - innerHeight - scrollTop < 200){
callNext();
}
}, 300);
마지막으로 handleScroll을 이벤트 등록을 해줍니다.
useEffect(()=>{
if(is_loading){return}
if(is_next){
window.addEventListener("scroll", handleScroll);
}else{
return () => window.removeEventListener("scroll", handleScroll)
}
return () => window.removeEventListener("scroll", handleScroll)
},[is_next, is_loading])
callNext()에서는 데이터를 불러오는 함수를 사용해줍니다.
'코딩 공부 노트 > React' 카테고리의 다른 글
리액트 검색엔진 최적화 하는 법 meta - tag, memo (0) | 2021.05.19 |
---|---|
댓글 사용하기, 댓글 알람주기 feat. firebase realtime DB (0) | 2021.05.14 |
Redux 미들웨어로 saga를 써야 할까? thunk를 써야할까? (0) | 2021.05.14 |
Firebase Storage 사용 : 이미지 저장 (0) | 2021.05.13 |
로그인, 회원가입 관리 (JWT, firebase) (0) | 2021.05.13 |