Skip to content

Commit 46ab408

Browse files
committed
📝 docs: useIntersectionObserver nextra 문서 작성
1 parent 209d8af commit 46ab408

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

docs/pages/docs/hooks/_meta.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"useTranslation": "useTranslation",
33
"useMousePosition": "useMousePosition",
4-
"useTimer": "useTimer"
4+
"useTimer": "useTimer",
5+
"useIntersectionObserver": "useIntersectionObserver"
56
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# useIntersectionObserver
2+
3+
## Introduce
4+
5+
IntersectionObserver API를 활용하여 요소의 가시성을 감지합니다.
6+
7+
```ts
8+
interface UseIntersectionObserverProps {
9+
root?: Element | null;
10+
rootMargin?: string;
11+
threshold?: number | number[];
12+
visibleOnce?: boolean;
13+
initialView?: boolean;
14+
onChange?: (isView: boolean, entry: IntersectionObserverEntry) => void;
15+
onEnter?: () => void;
16+
onLeave?: () => void;
17+
}
18+
19+
interface UseIntersectionObserverReturns {
20+
intersectionRef: Dispatch<SetStateAction<Element | null>>;
21+
isView: boolean;
22+
entry?: IntersectionObserverEntry | null;
23+
}
24+
25+
const useIntersectionObserver = (props: UseIntersectionObserverProps): UseIntersectionObserverReturns
26+
```
27+
28+
### Props
29+
30+
#### IntersectionObserver API 기본 옵션
31+
32+
- `root` : 뷰포트 대신 사용할 요소 객체 지정. 기본적으로 브라우저의 뷰포트가 사용됨(null)
33+
- `rootMargin` : Root의 범위를 확장하거나 축소시킴
34+
- `threshold` : observer가 실행되기 위한 최소한의 타켓의 가시성 비율
35+
36+
#### 부가옵션
37+
38+
- `initialView` : 초기 감지값 설정 옵션
39+
- `visibleOnce` : 처음 한번만 감지하는 옵션
40+
41+
#### callback 함수
42+
43+
- `onChange` : 타겟 Element의 가시성 상태가 변경될 때 호출할 콜백 함수
44+
- `onEnter` : 타겟 Element가 화면에 나타날 때 호출할 콜백 함수
45+
- `onLeave` : 타겟 Element가 화면에서 사라질 때 호출할 콜백 함수
46+
47+
### Returns
48+
49+
- `intersectionRef` : 훅에서 사용할 요소의 상태를 설정하는 데 사용되는 디스패치 함수. 감지하고자 하는 Element에 설정
50+
- `isView` : Element가 현재 뷰포트 내에 보이는지 여부를 나타내는 상태 값
51+
- `entry` : Intersection Observer API를 사용하여 Element의 교차 상태 관련 정보를 나타내는 객체
52+
53+
import { Callout } from 'nextra/components';
54+
55+
<Callout type="info">
56+
아래 공식문서에서 `entry`에 대한 더 자세한 사항을 확인할 수 있습니다.
57+
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry
58+
</Callout>
59+
60+
## Examples
61+
62+
### Lazy Loading
63+
64+
타겟 Element가 뷰포트에 보일때마다 리스트에 3개의 item이 비동기적으로 추가되는 예시
65+
66+
```tsx copy filename="TestComponent.tsx"
67+
const TestComponent = () => {
68+
const nextItemRef = useRef(1);
69+
const [items, setItems] = useState<number[]>([]);
70+
const [loading, setLoading] = useState(false);
71+
72+
const fetchItems = async () => {
73+
return new Promise<number[]>((resolve) => {
74+
setTimeout(() => {
75+
const newItems = [
76+
nextItemRef.current,
77+
nextItemRef.current + 1,
78+
nextItemRef.current + 2,
79+
];
80+
nextItemRef.current += 3;
81+
resolve(newItems);
82+
}, 1000);
83+
});
84+
};
85+
86+
const handleIntersectionChange = async (isView: boolean) => {
87+
if (isView && !loading) {
88+
setLoading(true);
89+
try {
90+
const newItems = await fetchItems();
91+
setItems((prevItems) => [...prevItems, ...newItems]);
92+
setLoading(false);
93+
} catch (error) {
94+
console.error(error);
95+
setLoading(false);
96+
}
97+
}
98+
};
99+
100+
const { intersectionRef } = useIntersectionObserver({
101+
threshold: 0.5,
102+
onChange: handleIntersectionChange,
103+
});
104+
105+
return (
106+
<div>
107+
<div style={{ height: '1000px' }}></div>
108+
<div
109+
style={{
110+
padding: '30px',
111+
backgroundColor: 'lightblue',
112+
}}>
113+
{items.map((item, index) => (
114+
<div
115+
key={index}
116+
style={{
117+
margin: '10px',
118+
height: '20px',
119+
backgroundColor: 'lightyellow',
120+
padding: '10px',
121+
}}>
122+
Item {item}
123+
</div>
124+
))}
125+
{loading && <p>아이템 로드 중...</p>}
126+
</div>
127+
<div ref={intersectionRef}> </div>
128+
</div>
129+
);
130+
};
131+
132+
export default TestComponent;
133+
```

0 commit comments

Comments
 (0)