Skip to content

Instantly share code, notes, and snippets.

@vczb
Created December 17, 2021 20:27
Show Gist options
  • Select an option

  • Save vczb/efa638da4a189ad1bd5817f97899dfec to your computer and use it in GitHub Desktop.

Select an option

Save vczb/efa638da4a189ad1bd5817f97899dfec to your computer and use it in GitHub Desktop.
React TS custom hook to intersection observer dom elements
import { useEffect, useState, useRef } from 'react'
export default function useOnScreen(ref?: any) {
const observerRef = useRef<IntersectionObserver | null>(null)
const [isOnScreen, setIsOnScreen] = useState(false)
useEffect(() => {
observerRef.current = new IntersectionObserver(([entry]) =>
setIsOnScreen(entry.isIntersecting)
)
}, [])
useEffect(() => {
if (observerRef.current && ref?.current) {
observerRef.current.observe(ref?.current)
return () => {
observerRef?.current && observerRef.current.disconnect()
}
}
}, [ref])
return isOnScreen
}
@vczb
Copy link
Author

vczb commented Dec 17, 2021

example usage:

import { useRef, useState, useEffect, HTMLAttributes } from 'react'

import Heading from 'components/Heading'
import { ReactNode } from 'react'
import * as S from './styles'
import useOnScreen from '../../hooks/use-on-screen'

export type SectionProps = {
  title?: string
  children: ReactNode
  color?: 'white' | 'black'
  titleMargin?: 'small' | 'medium' | 'large'
  sectionPadding?: 'medium' | 'large'
  isOnScreen?: boolean
} & HTMLAttributes<HTMLElement>

const Section = ({
  titleMargin = 'large',
  title,
  children,
  color = 'black',
  sectionPadding = 'medium',
  ...props
}: SectionProps) => {
  const ref = useRef(null)
  const [isOnScreen, setIsOnScreen] = useState(false)

  const onScreen = useOnScreen(ref)

  useEffect(() => {
    if (onScreen && !isOnScreen) {
      setIsOnScreen(true)
    }
  }, [isOnScreen, onScreen])

  return (
    <S.Wrapper
      ref={ref}
      isOnScreen={isOnScreen}
      titleMargin={titleMargin}
      sectionPadding={sectionPadding}
      {...props}
    >
      {!!title && <Heading color={color}>{title}</Heading>}
      {children}
    </S.Wrapper>
  )
}

export default Section

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment