Hide menu when scrolling in React.js
Tags: react, javascript
Published: 2019-02-10 11:26:32

---
title: Hide menu when scrolling in React.js
published: true
description: Hide or display a Navbar menu with React.js when the user scrolls up or down on the webpage.
tags: react, javascript
---

In this tutorial, I will explain how to make a *navbar* that is hidden or displayed when we scroll on the page. This is a version for **React.js** that uses the *State* of the component to know at all times what is the current state of our navbar.

## The component

Now we will see what parts our component needs. First of all, as we said that we will save the position of the scroll in our *State*, we will create a new value for the *State* inside the `constructor()`, which will take the initial value of the offset of the page.

Of course, we will also need the `render()` method that will return a `nav` with all the navbar items inside. Here's a first look:

```javascript
import React, { Component } from "react";
import classnames from "classnames";

export default class Navbar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      prevScrollpos: window.pageYOffset,
      visible: true
    };
  }

  render() {
    return (
      <nav
        className={classnames("navbar", {
          "navbar--hidden": !this.state.visible
        })}
      >
        <a href="#">Item 1</a>
        <a href="#">Item 2</a>
        <a href="#">Item 3</a>
      </nav>
    );
  }
}
```

Here's the CSS:

```css
.navbar {
  width: 100%;
  padding: 10px;
  position: fixed;
  top: 0;
  transition: top 0.6s;
}

.navbar--hidden {
  top: -50px;
}
```

Perfect, our component is ready to be viewed in a browser but does not yet have the behavior we want. Let's go for it!

First, we'll need to do the function that hides or displays the navbar. It will be called as if it was an event. It will see if the current offset is greater or less than the previous offset, depending on whether we scroll up or down. If the offset is bigger, we are going up, therefore it will display the menu. On the contrary, it is going to hide it. This show/hide behavior is managed by the **visible** state variable.

```javascript
handleScroll = () => {
  const { prevScrollpos } = this.state;

  const currentScrollPos = window.pageYOffset;
  const visible = prevScrollpos > currentScrollPos;

  this.setState({
    prevScrollpos: currentScrollPos,
    visible
  });
};
```

Now the function is done. But we need to call it every time the user scrolls on the screen. We will use *life cycle methods* to add and remove that listener in the scroll.

```javascript
componentDidMount() {
  window.addEventListener("scroll", this.handleScroll);
}

componentWillUnmount() {
  window.removeEventListener("scroll", this.handleScroll);
}
```

And with this, we finish our component. Next, I show all the whole code. I hope you liked it, I'll be uploading content more often. See you soon!

```javascript
import React, { Component } from "react";
import classnames from "classnames";

export default class Navbar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      prevScrollpos: window.pageYOffset,
      visible: true
    };
  }

  // Adds an event listener when the component is mount.
  componentDidMount() {
    window.addEventListener("scroll", this.handleScroll);
  }

  // Remove the event listener when the component is unmount.
  componentWillUnmount() {
    window.removeEventListener("scroll", this.handleScroll);
  }

  // Hide or show the menu.
  handleScroll = () => {
    const { prevScrollpos } = this.state;

    const currentScrollPos = window.pageYOffset;
    const visible = prevScrollpos > currentScrollPos;

    this.setState({
      prevScrollpos: currentScrollPos,
      visible
    });
  };

  render() {
    return (
      <nav
        className={classnames("navbar", {
          "navbar--hidden": !this.state.visible
        })}
      >
        <a href="#">Item 1</a>
        <a href="#">Item 2</a>
        <a href="#">Item 3</a>
      </nav>
    );
  }
}
```