서로 다른 컴포넌트에서 isInView 공유하기
3 minute read
2024-08-17
예시
랜딩페이지에서 CTA 버튼 으로 유저를 유도하는 장치가 아래와 같이 빈번하다.

하지만 가격 안내 섹션에는 다른 버튼이 그 역할을 중복 되게 담당하고 있기 때문에 숨겨주고 싶을 때가 있다.

코드
일단은 NextJS 에서 jotai 를 사용하기 위해서는 Provider 로 감싸서 싱글톤으로 관리되도록 할 수 있다.
세팅
import { PropsWithChildren } from 'react'
import { Provider } from 'jotai'
export const JotaiProvider = ({ children }: PropsWithChildren) => {
return <Provider>{children}</Provider>
}그리고 레이아웃에는 body 안에 넣어줘야 한다! 깜빡하면 삽질하게 된다.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko">
<body className={Pretendard.className}>
<JotaiProvider>
{children}
{/* ... */}
</JotaiProvider>
</body>
</html>
)
}전역 상태 선언
이제 컴포넌트 간 공유할 전역 상태를 선언해준다.
import { useAtom } from 'jotai'
import { atomWithImmer } from 'jotai-immer'
const priceAtom = atomWithImmer(false)
export const useIsInPriceView = () => useAtom(priceAtom)물론 위 예시에서는 immer 가 필요없다. primitive 값이기 때문에 차이가 없기 때문이다.
컴포넌트
주인공인 하단 CTA 버튼은 전역 상태에 따라 노출을 결정한다.
const variants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
}
const BottomCta = () => {
const [isInPriceView] = useIsInPriceView()
return (
<motion.div
initial="hidden"
animate={isInPriceView ? 'hidden' : 'visible'}
variants={variants}
>
{/* ... */}
</motion.div>
)
}그리고 다른 컴포넌트인 가격 섹션에서는 숨기려고 한다. 이 컴포넌트가 보일 때 값을 수정하면 된다.
const PriceSection = () => {
const ref = useRef(null)
const isInView = useInView(ref, {
margin: '-25% 0px -25% 0px',
// 1번째 -25% : 상단 viewport 에서 윗방향 더 커져서 `종료`
// 2번째 -25% : 하단에서 25% 떨어진 곳을 기준으로 `시작`
})
const [_, setIsInPriceView] = useIsInPriceView()
useEffect(() => {
if (isInView) {
setIsInPriceView(true)
} else {
setIsInPriceView(false)
}
}, [isInView, setIsInPriceView])
return (
<section
ref={ref}
id="price-section"
// ...
>
{/* ... */}
</section>
)
}