Skip to content

Commit

Permalink
feat(react): useIntersectionObserver 개선 및 InView, LazyImage 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
ssi02014 committed Jun 7, 2024
1 parent ddd8202 commit da4b8f7
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 239 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-weeks-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-kit/react': patch
---

feat(react): useIntersectionObserver 개선 및 InView, LazyImage 수정 - @ssi02014
118 changes: 88 additions & 30 deletions docs/docs/react/components/InView.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { InView } from '@modern-kit/react';

# InView

`Viewport`에 노출될 때 props로 넘겨주는 `action` 콜백 함수를 호출하는 컴포넌트입니다.
`InView`**[useIntersectionObserver](https://modern-agile-team.github.io/modern-kit/docs/react/hooks/useIntersectionObserver)**를 선언적으로 활용 할 수 있는 컴포넌트입니다.

`Viewport`에 노출될 때(`onIntersectStart`) 혹은 나갈 때(`onIntersectEnd`) 특정 action 함수를 호출 할 수 있는 컴포넌트입니다.

`calledOnceVisible`을 활용해 컴포넌트가 `viewport에 노출 될 때 한번 onIntersectStart을 호출` 할 수 있습니다.

Intersection Observer Option을 설정할 수 있습니다.(하단 `Note` 참고)

<br />

Expand All @@ -11,6 +17,18 @@ import { InView } from '@modern-kit/react';

## Interface
```ts title="typescript"
interface IntersectionObserverInit {
root?: Element | Document | null;
rootMargin?: string;
threshold?: number | number[];
}

interface UseIntersectionObserverProps extends IntersectionObserverInit {
onIntersectStart?: (entry: IntersectionObserverEntry) => void;
onIntersectEnd?: (entry: IntersectionObserverEntry) => void;
calledOnceVisible?: boolean;
}

type InViewProps = React.ComponentProps<'div'> & UseIntersectionObserverProps;

const InView: React.ForwardRefExoticComponent<
Expand All @@ -24,46 +42,86 @@ const InView: React.ForwardRefExoticComponent<
import { InView } from '@modern-kit/react';

const Example = () => {
const onAction = () => {
const handleIntersectStart = () => {
/* action */
}

const handleIntersectEnd = () => {
/* action */
}

return (
<div>
{/* ... */}
<InView action={onAction} calledOnce>Box1</InView>
</div>
<InView
onIntersectStart={handleIntersectStart}
onIntersectStart={handleIntersectEnd}
calledOnceVisible>
Box1
</InView>
</div>;
);
};
```

## Example

<div style={{ maxWidth: "500px", height: "500px", overflow: "scroll", background: "#f1f3f5" }}>
<div style={{ width: "100%", height: "600px", textAlign: 'center', fontSize: '2rem' }}>스크롤 해주세요.</div>
<InView
style={{ width: "100%", height: "300px", background: "#c0392B", color: "white", textAlign: 'center', fontSize: "21px" }}
action={() => console.log("action callback(1)")}
calledOnce
>
<div>
<p>Box1</p>
<p>브라우저 개발자 도구의 콘솔을 확인해주세요.</p>
<p>action 콜백 함수가 최초 1회만 호출됩니다.</p>
<p>calledOnce: true</p>
</div>
</InView>
<div style={{ width: "100%", height: "100px" }} />
<InView
style={{ width: "100%", height: "300px", background: "#89a5ea", color: "white", textAlign: 'center', fontSize: "21px" }}
action={() => console.log("action callback(2)")}
>
export const Example = () => {
const inViewStyle = {
width: '100%',
color: 'white',
textAlign: 'center',
fontSize: '21px',
padding: '0 20px',
}
return (
<div>
<p>Box2</p>
<p>브라우저 개발자 도구의 콘솔을 확인해주세요.</p>
<p>action 콜백 함수가 여러 번 호출됩니다.</p>
<p>calledOnce: false</p>
<div
style={{
height: '500px',
textAlign: 'center',
fontSize: '2rem',
}}>
스크롤 해주세요.
</div>
<InView
style={{
...inViewStyle,
background: '#c0392B',
}}
onIntersectStart={() => console.log('action onIntersectStart(1)')}
onIntersectEnd={() => console.log('action onIntersectEnd(1)')}
calledOnceVisible
>
<div>
<p>Box1</p>
<p>브라우저 개발자 도구의 콘솔을 확인해주세요.</p>
<p>onIntersectStart가 최초 1회만 호출됩니다.</p>
<p>calledOnceVisible: true</p>
</div>
</InView>
<div style={{ height: '300px' }} />
<InView
style={{
...inViewStyle,
background: '#89a5ea',
}}
onIntersectStart={() => console.log('action onIntersectStart(2)')}
onIntersectEnd={() => console.log('action onIntersectEnd(2)')}
>
<div>
<p>Box2</p>
<p>브라우저 개발자 도구의 콘솔을 확인해주세요.</p>
<p>onIntersectStart, onIntersectEnd 함수가 여러 번 호출됩니다.</p>
<p>calledOnceVisible: false</p>
</div>
</InView>
<div style={{ width: '100%', height: '900px', textAlign: 'center' }} />
</div>
</InView>
<div style={{ width: "100%", height: "600px", textAlign: 'center' }} />
</div>
);
};

<Example />

## Note
- [Intersection Observer API](https://developer.mozilla.org/ko/docs/Web/API/IntersectionObserver)
100 changes: 60 additions & 40 deletions docs/docs/react/components/LazyImage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { LazyImage } from '@modern-kit/react';

# LazyImage

`Viewport`에 노출될 때 할당된 이미지를 `Lazy Loading` 하는 이미지 컴포넌트입니다.
**[useIntersectionObserver](https://modern-agile-team.github.io/modern-kit/docs/react/hooks/useIntersectionObserver)**를 활용해 `Viewport`에 노출될 때 할당된 이미지를 `Lazy Loading` 하는 이미지 컴포넌트입니다.

`width`, `height` 값을 입력해 이미지의 크기를 조절 할 수 있으며, 동시에 `Layout Shift`를 개선할 수 있습니다.

Expand All @@ -15,13 +15,21 @@ Intersection Observer Option을 설정할 수 있습니다.(하단 `Note` 참고

## Interface
```ts title="typescript"
interface IntersectionObserverInit {
root?: Element | Document | null;
rootMargin?: string;
threshold?: number | number[];
}

interface LazyImageProps
extends React.ComponentProps<'img'>,
IntersectionObserverInit {
src: string;
}

const LazyImage: React.ForwardRefExoticComponent<Omit<LazyImageProps, "ref"> & React.RefAttributes<HTMLImageElement>>
const LazyImage: React.ForwardRefExoticComponent<
Omit<LazyImageProps, 'ref'> & React.RefAttributes<HTMLImageElement>
>;
```

## Usage
Expand Down Expand Up @@ -92,44 +100,56 @@ const Example = () => {

## Example

<div style={{ maxWidth: '500px', height: '500px', overflow:'scroll', background: '#f8f8f8' }}>
<div style={{ width: '100%', height: '500px', textAlign: 'center', fontSize: '2rem' }}>
스크롤 해주세요.
</div>
<LazyImage
width={"100%"}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/b5640bec-2abc-4205-afbf-ccfd9876a90b'
}
alt="img1"
onClick={() => console.log('img click1')}
/>

<div style={{ width: '100%', height: '150px' }} />

<LazyImage
width={"100%"}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/207743a7-b29f-4826-bc08-8df0d67e568b'
}
alt="img2"
onClick={() => console.log('img click2')}
/>

<div style={{ width: '100%', height: '150px' }} />

<LazyImage
width={"100%"}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/d1957ec8-fe87-406e-bfda-fb4ee505b152'
}
alt="img3"
onClick={() => console.log('img click3')}
/>
</div>
export const Example = () => {
return (
<div style={{ background: '#f8f8f8' }}>
<div
style={{
height: '500px',
textAlign: 'center',
fontSize: '2rem',
}}>
스크롤 해주세요.
</div>
<LazyImage
width={'100%'}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/b5640bec-2abc-4205-afbf-ccfd9876a90b'
}
alt="img1"
onClick={() => console.log('img click1')}
/>

<div style={{ width: '100%', height: '150px' }} />

<LazyImage
width={'100%'}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/207743a7-b29f-4826-bc08-8df0d67e568b'
}
alt="img2"
onClick={() => console.log('img click2')}
/>

<div style={{ width: '100%', height: '150px' }} />

<LazyImage
width={'100%'}
height={400}
src={
'https://github.com/Team-Grace/devgrace/assets/64779472/d1957ec8-fe87-406e-bfda-fb4ee505b152'
}
alt="img3"
onClick={() => console.log('img click3')}
/>
</div>
);
};

<Example />


## Note
- [Intersection Observer API](https://developer.mozilla.org/ko/docs/Web/API/IntersectionObserver)
Loading

0 comments on commit da4b8f7

Please sign in to comment.