An error occurred while attempting to access the 'classList' property in React due to null values

Seeking assistance with altering the background color of a header upon scroll. I keep receiving null when trying to reference the navbar variable. Any suggestions on how I can achieve this effect? Utilizing transform:translateY for a subtle scroll animation.

import React from 'react'
import { Navbar, Container, Nav } from 'react-bootstrap'

import { LinkContainer } from 'react-router-bootstrap'

const Header = () => {

    const navbar = document.getElementById("navbar");
    let scrolled = false;

    window.onscroll = function () {
        if (document.body.scrollTop >= 200 || document.documentElement.scrollTop >= 200) {
            navbar.classList.add('color-nav');
            if (!scrolled) {
                navbar.style.transform = 'translateY(-70px)'
            }
            setTimeout(function () {
                navbar.style.transform = 'translateY(0px)'
                scrolled = true

            }, 200)
        } else {
            navbar.classList.remove('color-nav');
            scrolled = false
        }
    };

    return (
        <div id='navbar' >
            <Navbar fixed="top" className='navbar' collapseOnSelect expand="lg"  >
                <Container>
                    <LinkContainer to='/'>
                        <Navbar.Brand className='logo' >Logo</Navbar.Brand>
                    </LinkContainer>
                    <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                    <Navbar.Collapse id="responsive-navbar-nav">
                        <Nav className="me-auto">
                            <LinkContainer to='/services'>
                                <Nav.Link className='links'>Services</Nav.Link>
                            </LinkContainer>
                        </Nav>
                        <Nav>
                            <LinkContainer to='/login'>
                                <Nav.Link className='links'>Login</Nav.Link>
                            </LinkContainer>
                            <LinkContainer to='/signup'>
                                <Nav.Link className='links'>
                                    Sign Up
                                </Nav.Link>
                            </LinkContainer>
                        </Nav>
                    </Navbar.Collapse>
                </Container>
            </Navbar>
        </div >
    )
}

export default Header

https://i.sstatic.net/LnPy3.png

Answer №1

It seems like your approach may not align with the recommended React methodology. In order to access the navbar element, it is advisable to utilize the useRef hook. This will provide a straightforward reference to the element throughout the component's lifecycle.

In addition to that, there are several other issues that require attention:

  • The variable scrolled is declared using useState, but it does not seem to be utilized properly.
  • Your scroll listener should be implemented within a useEffect. Currently, your code is setting a new listener on each re-render of the component, which is not ideal. It should only be set once.
  • The cleanup for your scroll listener is missing.

I've made some modifications to the code that I believe will address these concerns effectively.

import React, { useState, useRef, useEffect } from "react";
import { Navbar, Container, Nav } from "react-bootstrap";

import { LinkContainer } from "react-router-bootstrap";

const Header = () => {
  const [scrolled, setScrolled] = useState(false);
  const navRef = useRef();

  useEffect(() => {
    const handleScroll = () => {
      if (
        document.body.scrollTop >= 200 ||
        document.documentElement.scrollTop >= 200
      ) {
        navRef.current.classList.add("color-nav");

        if (!scrolled) {
          navRef.current.style.transform = "translateY(-70px)";
        }

        setTimeout(function () {
          navRef.current.style.transform = "translateY(0px)";
          setScrolled(true);
        }, 200);
      } else {
        navRef.current.classList.remove("color-nav");
        setScrolled(false);
      }
    };

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  return (
    <div id="navbar" ref={navRef}>
      <Navbar fixed="top" className="navbar" collapseOnSelect expand="lg">
        <Container>
          <LinkContainer to="/">
            <Navbar.Brand className="logo">Logo</Navbar.Brand>
          </LinkContainer>
          <Navbar.Toggle aria-controls="responsive-navbar-nav" />
          <Navbar.Collapse id="responsive-navbar-nav">
            <Nav className="me-auto">
              <LinkContainer to="/services">
                <Nav.Link className="links">Services</Nav.Link>
              </LinkContainer>
            </Nav>
            <Nav>
              <LinkContainer to="/login">
                <Nav.Link className="links">Login</Nav.Link>
              </LinkContainer>
              <LinkContainer to="/signup">
                <Nav.Link className="links">Sign Up</Nav.Link>
              </LinkContainer>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    </div>
  );
};

export default Header;

Answer №2

Attempting to access the navbar before it's rendered will result in a null variable. Utilize Refs in React to interact with node elements directly. For additional information, check out this resource.

Answer №3

It seems like you're not approaching this in a React-friendly manner. There are several ways to tackle this issue, one of which involves utilizing the useState hook to keep track of scrolling and updating it when the height changes. This way, you can easily switch between classNames using a ternary operator in JSX:

<div className={scrolled ? "color-nav" : "something"}>

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 AJAX to send a POST request with the PHP $_FILES superglobal while preventing the default form submission with the onclick

Seeking to implement a photo upload form using an AJAX script that is currently in place. Currently, I have the html form with a file input field. Upon submission, there is an onclick event triggering "PostForm(); return false;" This action directs to a ...

Why won't angularjs interpret my object accurately?

Currently, I am in the process of developing an angularjs application and I have encountered a minor issue. The problem arises when I populate a list of projects and then apply filtering based on certain conditions. Visually, everything appears fine on the ...

How does assigning a checkbox's value as 'undefined' result in the addition of ng-invalid?

I'm facing an issue with a checkbox in my Angular project. The checkbox has a false value of undefined, and even though it's not marked as required, the form doesn't validate when I check and uncheck it. This is because the class ng-invalid ...

Tips on displaying Vue objects row by row

I am currently working on a Vue application where I want to display each 'object' in its own table row. However, I'm facing an issue where the objects are being displayed in one column or as separate rows. Is there a way to ensure that &apos ...

Footer obscures content above it

Currently, I am encountering an issue with my jQuery menu slide where my footer is causing some problems. Whenever I zoom in, the footer ends up overlapping all of my other content. This results in a situation where if the website is viewed on a smaller r ...

Tips for utilizing conditional CSS effectively in CakePHP 2.x

I need help translating this code: <!--[if IE 7]> <link rel="stylesheet" type="text/css" href="css/ie7-style.css" /> <![endif]--> into CakePHP. Currently, I am using $this->Html->css('fileName') in the view file an ...

Move to Fieldset Upon Link Click

Here's an example of what I have implemented so far here It's evident that this is not fully functional due to the PHP and jQuery integration. This demo is just a showcase of my progress. I am looking to create a functionality where clicking on ...

The function res.map() cannot be used in this context because res is an Array Object

I am dealing with data in the following format: [ { device_id: '12335', timestamp: '2018-05-14T08:31:23.000Z', temperature: 21, pressure: 31, humidity: 20, equipment_name: 'truck5' }, { device_id: &apo ...

Ways to remove the default classes added by ngbootstrap

My current challenge involves utilizing ngbootstrap for popovers, yet desiring to override its default styling. Specifically, I have a form that should function as a popover triggered by a button click, and it needs to maintain its own distinct styles. Up ...

Using CSS min-height: 100vh will ensure that the container has enough height to fill the entire viewport

Utilizing min-height: 100vh; in my inner call to action div placed on top of a background video has been mostly successful. However, I've encountered an issue where using 100vh with the absolutely positioned video seems to introduce an unwanted margin ...

JavaScript object properties and the concept of inheritance

Currently, I am teaching myself JavaScript, but the concept of prototyping and inheritance in JavaScript is puzzling to me. Example 1: function MyClass() { this.my_var = "1"; } function MyClass2() { this.my_var2 = "2"; } MyClass2.prototype = ne ...

Locating the DataGrid Component in Material-UI v5: A Guide on Installing DataGrid in React

After updating material-ui/core to version 5.0.0-beta.1 and material-ui/lab to version 5.0.0-alpha.30, I am unable to find the DataGrid component. It does not seem to be included in either material-ui/core or material-ui/lab. Additionally, the documentat ...

Using JavaScript to assess the outcome of a form utilizing an if statement

Trying out a method to assess a result by utilizing an if statement on the form provided below. Upon dividing the 2nd result by the 1st result, an average percentage is calculated. If this percentage is equal to or higher than 55, then the outcome is label ...

React-app size has grown larger post-deployment

I recently created my second app clone using React. I have noticed that after deployment, the size of the app increases. Everything looks normal on localhost:3000, but it significantly grows once deployed. Any assistance in resolving this issue would be gr ...

Uploading website to Azure: In order to view the latest version of the website [using ASP.NET and REACT], it is essential to clear the cached content

When deploying my website to Azure from VS 2017, I consistently encounter the need to clear my browser cache in order to see the latest version of the site (or use ctrl+f5 to bypass cached content when refreshing). Unfortunately, this poses a challenge for ...

Flipping and expanding cards with CSS3

I am attempting to create a layout with a collection of cards/divs within a container. When a card/div is clicked, it should flip horizontally and expand to occupy the entire space within the container (essentially resizing to 100% x 100% when clicked). I ...

When utilizing a method that is not a class or prototype, the issue with Access-Control-Allow-Origin blocking the origin file:// does not occur

Dealing with a CORS issue, I found a solution using jsonp and callback=? as recommended in the discussion on XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin Additionally, I enabled '--allow-file-access-from-files' ...

Combining Multiple Routes with Redirect using React Router

If I have an authentication token and a function called checkToken, how can I efficiently reroute from multiple routes using React Router to avoid repetition like the example below? <Route exact path="/" render={() => { return checkToken() ? (< ...

Bootstrap 4's mobile flexbox expends beyond the desired width

I'm facing an issue with my code snippet: <div class="row"> <div class="w-100 col-auto col-lg-5 w-auto p-3 p-lg-5 m-4 rounded-sm bg-dark text-white shadow-lg"> <h3>This is a very very very long Text</h3> </ ...

How about locking the initial column of a table and ensuring a uniform height with the header row configured to wrap any excess whitespace?

My goal is to create an HTML table with specific properties: The first column should be frozen The text on the header row should be wrapped Although it sounds simple, I am encountering an issue where the height of the first column in the header row is i ...