Skip to content

Instantly share code, notes, and snippets.

@whoisryosuke
Created February 19, 2020 20:30
Show Gist options
  • Save whoisryosuke/72d9979a44e01e95400760d98ca519e8 to your computer and use it in GitHub Desktop.
Save whoisryosuke/72d9979a44e01e95400760d98ca519e8 to your computer and use it in GitHub Desktop.
React - Hide nav/header/footer on scroll -- via: https://dev.to/n8tb1t/tracking-scroll-position-with-react-hooks-3bbj

The hook

useScrollPosition.js:

import { useRef, useLayoutEffect } from 'react'

const isBrowser = typeof window !== `undefined`

function getScrollPosition({ element, useWindow }) {
  if (!isBrowser) return { x: 0, y: 0 }

  const target = element ? element.current : document.body
  const position = target.getBoundingClientRect()

  return useWindow
    ? { x: window.scrollX, y: window.scrollY }
    : { x: position.left, y: position.top }
}

export function useScrollPosition(effect, deps, element, useWindow, wait) {
  const position = useRef(getScrollPosition({ useWindow }))

  let throttleTimeout = null

  const callBack = () => {
    const currPos = getScrollPosition({ element, useWindow })
    effect({ prevPos: position.current, currPos })
    position.current = currPos
    throttleTimeout = null
  }

  useLayoutEffect(() => {
    const handleScroll = () => {
      if (wait) {
        if (throttleTimeout === null) {
          throttleTimeout = setTimeout(callBack, wait)
        }
      } else {
        callBack()
      }
    }

    window.addEventListener('scroll', handleScroll)

    return () => window.removeEventListener('scroll', handleScroll)
  }, deps)
}

Use hook in component.

component.jsx:

import React, { useState } from "react"

import { useScrollPosition } from "../hooks/useScrollPosition"

export default function Footer() {
  const [sticky, setSticky] = useState(false)

  useScrollPosition(
    ({ prevPos, currPos }) => {
      const isShow = currPos.y > prevPos.y
      if (isShow !== sticky) setSticky(isShow)
    },
    [sticky]
  )

  return (
    <Box
      as="footer"
      mb="-1em"
      sx={{
        position: "sticky",
        transform: sticky ? "translateY(100%)" : "translateY(0)",
        transition: "transform 400ms ease-in",
        bottom: 0,
        left: 0,
      }}
    >
      © {new Date().getFullYear()}
    </Box>
  )
}
@ordercloudbg
Copy link

Very useful, thanks!

@markwybrow
Copy link

This is great - Thanks ... Might pay to mention you are using chakra-ui here ... well I think you are

@gmbhatti
Copy link

Good!

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