-
Notifications
You must be signed in to change notification settings - Fork 7
Week 4 Infinite Scroll
SeonJun Hwang edited this page Nov 26, 2019
·
1 revision
- Pagination을 이용하는 한 기법
- 스크롤을 기준으로 하단에 스크롤이 도착하면 기준에 부합하는 다음 페이지를 읽어오는 기법
- 계산을 하기 때문에 원하는 타이밍에 fetch작업을 진행
- 코드만 봐도 상당히 직관적인 작업
- dom객체에 직접 접근한다는 점이 react에 맞는 점인지는 의문 🤔
const curScroll // 현재 스크롤의 위치 ( 스크롤이 시작하는 위치 기준 )
const scrollHeight // 스크롤의 길이
const windowTotalHeight // 스크롤 전체의 길이
// 무한스크롤 조건
if (curScroll + scrollHeight === windowTotalHeight)
fetch(...)
확실히 누가봐도 코드가 상당히 직관적이다.
하지만 scroll Event는 자주 발생 + 비용이 높다.
즉 사용하면 사용할수록 성능이 저하되고 렌더링이 깔끔하지 못하다.
- 비동기로 작업 처리
- 특정 컴포넌트가 노출되는 정도에 따라 사용자 지정 작업을 실행
- Scroll 관련 연산이 적어 Cost가 적다
- 비동기기 때문에 렌더링이 깔끔하고 스크롤이 부드러움
- Custom Hook을 사용해야 한다 ( 왜인지는 잘 모르겠다 )
useIntersection.jsx
// Custom Hook
import { useState, useEffect, useCallback } from "react";
// 기본 옵션, 목표 컴포넌트의 50%가 보이면 실행된다.
const baseOption = {
root: null,
threshold: 0.5,
rootMargin: "0px"
};
const useIntersect = (onIntersect, option) => {
const [ref, setRef] = useState(null);
const checkIntersect = useCallback(([entry], observer) => {
if (entry.isIntersecting) {
onIntersect(entry, observer);
}
}, []);
useEffect(() => {
let observer;
if (ref) {
observer = new IntersectionObserver(checkIntersect, {
...baseOption,
...option
});
observer.observe(ref);
}
return () => observer && observer.disconnect();
}, [ref, option.root, option.threshold, option.rootMargin, checkIntersect]);
return [ref, setRef];
};
export default useIntersect;
infiniteScroll.jsx
//Intersection Components를 사용하는 부분
//작업을 비동기로 처리한다.
const [_, setRef] = useIntersect(async (entry, observer) => {
observer.unobserve(entry.target)
const nextData = await fetcher()
const nextComponents = drawer(nextData)
setList(prev => [...prev, ...nextComponents])
if (nextData.length) observer.observe(entry.target)
}, {})
- Android의 ListBox, RecylcerView 처럼 Custom Component로 넣을 수는 없나?
- 특정 위치에 도착하면 이벤트가 발생하는건 확정, 무엇을 받아야 할까?
- 외부에서 render된 컴포넌트를 받으니 hooks 규칙 위반, 그렇다면?
- data와 component를 그리는 drawer로 나눠서 받는다.
// 컴포넌트
// data를 읽어오는 fetcher랑 drawer로 나눠서 받는다.
const Component = ({ fetcher, drawer }) => {
const [loadding, setLoadding] = useState(true)
const [list, setList] = useState([])
useEffect(() => {
;(async () => {
// data를 fecther로 읽어온다.
const data = await fetcher()
// 읽어온 정보를 drawer에 넘겨 component로 바꿔준다.
const initComponents = drawer(data)
setLoadding(false)
// 바꾼 내용을 내부 상태에 넣어주면? Hooks 문제 없이 정상적으로 받아진다.
setList(prev => [...initComponents])
})()
}, [])
- 외부에서 render된 후 해당 컴포넌트를 넘겨 받아 처리하려고 하니 Hooks rule 위반이다. 왜일까?
- 재사용성 과연 이게 높아진걸까?
- 나름 라이브러리처럼 만들어서 따로 뺄 수 있을것 같다. 과연?
부스트캠프 맴버십 - 그룹프로젝트 (서준배, 최성찬, 홍승표, 황선준)