Elevate the React experience by smoothly sliding a fixed navbar upwards when scrolling down, and elegantly sliding it

tl;dr Don't miss the solution at the end!

Looking to create a slide up and down effect on a fixed navbar in react?

What's the best approach - using refs or the componentDidMount lifecycle hook?

  hideNav = (navbar) => {
    const hide = () => {
      let lastScrollTop = 0;
      const currentScrollTop = navbar.scrollTop;

      // scrolling down
      if (currentScrollTop > lastScrollTop) {
      navbar.classList.add('hidden');
      } else {
      // scrolling up
        navbar.classList.remove('hidden');
      }
      lastScrollTop = currentScrollTop;
    };

    window.addEventListener('scroll', hide);
  };

... scroll further down in the render method:

 render() {
      return <Navbar ref={this.hideNav} />

UPDATE:

Here is the solution:

class Navbar extends React.Component {
  state = {
    auth: false,
    slide: 0,  // Set how much the Navbar should slide up or down
    lastScrollY: 0,  // Keep track of current position in state
  };

  componentWillMount() {
    // Start listening for scroll changes when this component mounts
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    // Stop listening for scroll changes when this component is unmounted
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = () => {
    const { lastScrollY } = this.state; 
    const currentScrollY = window.scrollY;


    if (currentScrollY > lastScrollY) {
      this.setState({ slide: '-48px' });
    } else {
      this.setState({ slide: '0px' });
    }
    this.setState({ lastScrollY: currentScrollY });
  };

   render() {    
    return (
      <Navbar
        style={{
          transform: `translate(0, ${this.state.slide})`,
          transition: 'transform 90ms linear',
        }}
      />
     );
   }
 }

No optimizations are done yet, so it's suggested to throttle the event using requestAnimationFrame, setTimeout, or customEvent. Check here for an example.

Answer №1

It's not recommended to use refs for registering event listeners or manipulating classes. Instead, it's better to utilize component lifecycle hooks for handling scroll events on the window as you suggested.

export default class App extends Component {
  state = { hidden: false };

  constructor(props) {
    super(props);
  
    this.handleScroll = this.handleScroll.bind(this);
  }

  componentWillMount() {
    window.addEventListener('scroll', this.handleScroll);
  }

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

  handleScroll(e) {
    let lastScrollTop = 0;
    const currentScrollTop = navbar.scrollTop;

    if (!this.state.hidden && currentScrollTop > lastScrollTop) {
      this.setState({ hidden: true });
    } else if (this.state.hidden) {
      this.setState({ hidden: false });
    }
    lastScrollTop = currentScrollTop;
  }

  render() {
    return (
      <Navbar hidden={this.state.hidden} />
    );
  }
}

Regarding the scroll function provided, there seems to be an issue with lastScrollTop always being set to 0. For a better solution, you can refer to this answer that addresses a similar scenario for creating a fixed navbar on scroll (with hiding instead of showing): Sticky Header after scrolling down

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using a JavaScript class rather than an ID for toggling visibility

As a complete newbie to JavaScript, I've come across similar questions but I'm lost when it comes to coding - help needed! So here's the code I have so far, and I'm hoping someone can assist me. Currently, I have JavaScript set up to s ...

The D3.extent() function is raising a TypeError because it is unable to iterate over the

I have been struggling with this issue for the past few hours, and I could really use some help. I'm not very familiar with using D3 in conjunction with React. Essentially, I have an anomaly detection algorithm running on the backend Flask App that r ...

Using JavaScript regular expressions to validate currency without relying on jQuery

Looking for a solution to create a money mask for an input field without using jquery in my application. Is it possible to achieve this using regular expressions with 'on key up' events, for example? Below is the code snippet: <tr> & ...

I am unable to generate a vite application within WSL

My system is running node version 10.19.0 and npm version 6.14.4. Whenever I try to run create-vite@latest client, I encounter the following error: npx: installed 1 in 0.79s /home/victor/.npm/_npx/86414/lib/node_modules/create-vite/index.js:3 import &apos ...

Choosing a value from a dropdown automatically based on the selection of a specific value from another dropdown

Currently, I am working on a project that involves selecting a value from a dropdown menu based on the selection from another dropdown menu. var gender1 = document.querySelector("#gender1"); var gender2 = document.querySelector("#gender2"); gender1.add ...

The value in my Reactjs application seems to only update after I refresh the page, but not consistently

const availableFunc = (id) => { if (Active.length > 0) { let available = Active.filter((obj) => obj.type === id).map((obj) => obj.available !== undefined ? obj.available : "" ); return available[0]; } }; All the ...

Sending a parameter from a Pug template to JSX

I am currently in the process of developing a game using Express and React. My main challenge lies in accessing the userId within my index.jsx file to execute certain actions on my controllers, such as increasing the user's score. The route I have se ...

Transform JSON String into Object using jQuery

Recently, I came across a JSON String in this format. {"label":"label","label1":"67041","label2":"745","label3":"45191","label4":"11‌​464"} I needed to convert it into an object structure like this [{"label":"label","label1":"67041","label2":"745"," ...

Exploring the option of eliminating the email field from the PHP redirect function and transforming it into a pop-up notification

I am currently utilizing the following code to send an email notification to my address whenever a new user signs up: <?php $errors = ''; $myemail = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0ded1ddd ...

Ways to align text in a table row in a way that it remains positioned at the center of the screen's visible area

Can anyone assist me with this task? I need help centering text within a table row ('Some text here...') so that it always appears in the middle of the screen. The table will have horizontal scrolling. .compare-content { max-width: 480px; ...

Is there a way to retrieve the fields of an index in elastic search?

After receiving a JSON object from an elastic search query, I successfully extracted the data using the code snippet below: $scope.results = response.hits.hits; console.log($scope.results); var resultstofilter = []; var resultArray = []; ...

When working with ReactJS, I encountered an issue where reading values from a JSON object was straightforward at the first level, but

This is a code snippet for rendering user items in an accordion display: const UserItem = (user, index) => ( <div key={index} className="accordion__item js-accordion-item"> <div className="accordion-header js-accordion-header">{(index ...

Issues with the display property

After setting the display of a div tag as none in the style property, I am trying to show it based on an on-click function. However, the issue I am facing is that when I click on the function, the div displays for a brief moment then disappears again. Ca ...

Creating a customized component using unique styles in Material UI version 1

Currently, I am facing a challenge in styling my Card component with a width of 75 pixels while using Redux and Material UI V1. Despite following the example provided by Material UI on custom styling through withStyles and connect, I have not been able to ...

Is IPv6 like a JavaScript string in any way?

Introduction In the era of IPv4, life was simpler as IPv4 addresses could easily be converted into 32-bit integers for various calculations. However, with the introduction of IPv6, things have become more complicated due to the lack of native support for ...

The latest grid system in Bootstrap 5 is designed to streamline

I'm attempting to use Bootstrap 5 to create a grid system similar to the image shown below View Image I've been struggling to replicate the grid section shown in the attached image using Bootstrap 5. <div class="container-fluid"> ...

Implementing a Slide animation in React

I am currently working on a carousel feature that includes two buttons, Next and Previous. When the user clicks on Next, I want the carousel to slide from left to right, and when they click on Previous, it should slide from right to left. One important not ...

Validation of Single Fields in Angular Reactive Forms

When I validate a reactive form in Angular, I expect the error message to show up beneath the invalid field whenever incorrect data is entered. <form (ngSubmit)=sendQuery() [formGroup]="form"> <div *ngFor='let key of modelKeys&ap ...

Leveraging the power of PHP includes with nested subdirectories

Hello, I recently configured my web server to run all .html files as .php files, allowing me to utilize the php include function, which has been very beneficial. However, I have various subdirectories with multiple files in each one. Homepage --banners ...

Ignoring TypeScript overloads after the initial overload declaration

Issue An error occurs when attempting to call an overload method for a specific function. The call only works for the first defined overload, causing an error if the call is made to the second overload with mismatched typing compared to the first overload ...