Coolhead

Coolhead

Navbar hide and show on Scroll using Custom React Hooks

Navbar hide and show on Scroll using Custom React Hooks

implementing smooth navbar using custom react hooks

Making a Custom React Hook

code:

/**
 * useScroll React custom hook
 * Usage:
 *    const { scrollX, scrollY, scrollDirection } = useScroll();
 */

 import { useState, useEffect } from "react";

 export function useScroll() {
    // storing this to get the scroll direction
   const [lastScrollTop, setLastScrollTop] = useState(0);
    // the offset of the document.body
   const [bodyOffset, setBodyOffset] = useState(
     document.body.getBoundingClientRect()
   );
    // the vertical direction
   const [scrollY, setScrollY] = useState(bodyOffset.top);
    // the horizontal direction
   const [scrollX, setScrollX] = useState(bodyOffset.left);
    // scroll direction would be either up or down
   const [scrollDirection, setScrollDirection] = useState();

   const listener = e => {
     setBodyOffset(document.body.getBoundingClientRect());
     setScrollY(-bodyOffset.top);
     setScrollX(bodyOffset.left);
     setScrollDirection(lastScrollTop > -bodyOffset.top ? "down" : "up");
     setLastScrollTop(-bodyOffset.top);
   };

   useEffect(() => {
     window.addEventListener("scroll", listener);
     return () => {
       window.removeEventListener("scroll", listener);
     };
   });

   return {
     scrollY,
     scrollX,
     scrollDirection
   };
 }

Styles

I am using css-in-javascript to set the visibility of the nav bar but you can use whatever you like.

const styles = {
    active: {
      visibility: "visible",
      transition: "all 0.5s"
    },
    hidden: {
      visibility: "hidden",
      transition: "all 0.5s",
      transform: "translateY(-100%)"
    }
  }

Finale code would look like this

import React from 'react';

import {useScroll} from './../../hooks/useScroll'

export default function Navbar() {
  const { y, x, scrollDirection } = useScroll();  

  const styles = {
    active: {
      visibility: "visible",
      transition: "all 0.5s"
    },
    hidden: {
      visibility: "hidden",
      transition: "all 0.5s",
      transform: "translateY(-100%)"
    }
  }

    return (
        <nav className="Header" style={scrollDirection === "down" ? styles.active: styles.hidden}   >
        <Link to="/" className="Header__link">
            <img src={Logo} height="50px" width="auto" alt="logo"/>
            <div className="Header__link__title">
              Chronology
            </div>
        </Link>  
        <ul className="flex">
            <li>
              <Link to="/about" className="Header__link">About</Link>
            </li>
            <li>
              <Link to="/blog" className="Header__link">Blogs</Link>
            </li>
          </ul>
        </nav>       
    )
}

I know this is very lazy writing but it's already midnight.

I will write in detail about it.

I hope it help someone.

Impressum

You can connect with me on Twitter | LinkedIn || github

Proudly part of