Cannot read properties of null reading classlist ошибка

It should be <div className="dropdown"> instead of <div class="dropdown"> and <div id={styles.myDropdown} className={styles.dropdownContent}>

You would also avoid doing vanilla js inside a react/next app.

You would instead have a react state like this:

const [dropdownToggled, toggleDropdown] = useState(false);
  
const handleClick = () => {
  toggleDropdown(!dropdownToggled);
};

And have a condition on whether your jsx have a className hidden that sets display: none

something like this:

     <div
      className={`${styles.dropdownContent} 
      ${dropdownToggled ? styles.hidden : ""}`}
     >
       <a href="/">Link 1</a>
       <a href="/">Link 2</a>
       <a href="/">Link 3</a>
     </div>

To make the dropdown close when the user clicks outside, you would have a div like this:

<div
  className={styles.backdrop}
  onClick={() => toggleDropdown(true)}
></div>

that is styled like this:

.backdrop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: -1;
}

Now since this div takes the whole screen and is positioned absolute when the user clicks anywhere on the page the onClick will fire and toggle the dropdown.

Working CodeSandbox.

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Open

lekoala opened this issue

Oct 6, 2022

· 15 comments

Comments

@lekoala

Prerequisites

  • I have searched for duplicate or closed issues
  • I have validated any HTML to avoid common problems
  • I have read the contributing guidelines

Describe the issue

I’m having the following issue in production on one website

Cannot read properties of null (reading ‘classList’)

At the lines

this._element.classList.add(CLASS_NAME_HIDE) // @deprecated
this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW)
EventHandler.trigger(this._element, EVENT_HIDDEN)

My guess is that the element is already removed when that callback is called (i’m calling .dispose in the bs.hidden callback event I don’t know if that’s related or not. it should work without issues either way in my opinion).

Reduced test cases

My proposal is to simply add a null check before and return early if this._element is null

Demo
https://codepen.io/lekoalabe/pen/oNdPNXJ

click create modal
click create toast
accept sweet alert modal
try to click close icon on toast => it triggers the error

What operating system(s) are you seeing the problem on?

Windows

What browser(s) are you seeing the problem on?

Chrome

What version of Bootstrap are you using?

v5.2.2

@github-actions

Hello @lekoala. Bug reports must include a live demo of the issue. Per our contributing guidelines, please create a reduced test case on CodePen or StackBlitz and report back with your link, Bootstrap version, and specific browser and Operating System details.

@lekoala

ok so it’s kind of hard to replicate but here it goes

it can trigger a variety of errors I’ve listed in the codepen

i have to admit it’s a bit extreme to have sweetalert, modals and toasts all over the place, but it shouldn’t create js error anyway

you have to click around a fair bit to trigger the various error. the toast error is caused like this:

  • click create modal
  • click create toast
  • accept sweet alert modal
  • try to click close icon on toast => it triggers the error

@debadutta98

ok so it’s kind of hard to replicate but here it goes

it can trigger a variety of errors I’ve listed in the codepen

i have to admit it’s a bit extreme to have sweetalert, modals and toasts all over the place, but it shouldn’t create js error anyway

you have to click around a fair bit to trigger the various error. the toast error is caused like this:

  • click create modal
  • click create toast
  • accept sweet alert modal
  • try to click close icon on toast => it triggers the error

This issue is related to #37245

@lekoala

@lekoala

i’m not sure adding null checks will fix the root cause, but at least it would prevent js errors. these errors don’t seem to prevent expected behaviour, so I think it should be pretty safe to add them.

@GeoSot

I had a «quick» look to the given codepen.

  • You have imported the bootstrap.bundle.js twice, that was causing modal.js:357 Uncaught TypeError: Cannot read properties of null (reading 'hide')

  • plus, I couldn’t spot any referral to bootstrap.Toast 😖

image

Is a bit strange to find an error on bootstrap toast, without using it. 😵‍💫

@lekoala

@GeoSot sorry about that indeed i tried a couple of variations and indeed i left a duplicate import. without it i dont have the issue anymore (it still happens (without duplicates) in prod in another app but it’s hard to replicate the exact setup).
not sure why importing twice would break everything though?

I’m using a «toaster» helper method that calls new bootstrap.Toast under the hood, i can extract this helper if that makes anything clearer but in any case, without the duplicate import i didn’t find a way to replicate my issue

@GeoSot

For sure, I can try to help only if you use the Bs components explicitly, and not inside another library. It is not possible to guess any side effects

@lekoala

@GeoSot so i managed to replicate it finally!
basically it’s very tricky to get it by hand, which is why it happens rarely
if you click or double click on the close icon right when it’s supposed to close, it may fail
I’ve simulated this with a setTimeout
image

@GeoSot

I tried it a lot in comparison with a ‘native’ toast. On your codepen example, for some reason (not able to debug all these lines 😞), the second click of the double-click, seems, it is finding the event listener still registered, so it tries to execute the hide process twice. In contradiction, this cannot be replicated on a native toast https://getbootstrap.com//docs/5.2/components/toasts/#live-example

So maybe the better scenario is to try to decouple the code a bit, or try to refactor based on the given events

@lekoala

@GeoSot ok fair point i’ve simplified the example even more and I think I found the actual issue:

  • if you use autohide
  • and you dispose of the instance on hidden
  • if someone tries to click on the close icon, you get an error

what do you think? Maybe disposing of the class after hidden is not a good idea?

@GeoSot

Soooo I found some time to try your code

Using your script with some minor changes (you will find below), seems, it works ok

const html = `<div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <small>11 mins ago</small>
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
  </div>
  </div>`;

document.getElementById("toast-me").addEventListener("click", ev => {
  const container = document.getElementById("toast-container");
  container.innerHTML = container.innerHTML + html;

  const toastElList = document.querySelectorAll(".toast");
  console.log(toastElList.length);
   toastElList.forEach(toastEl => {

    const inst = bootstrap.Toast.getOrCreateInstance(toastEl, {
      autohide: true
    });
    inst.show();

    toastEl.addEventListener(
      "hidden.bs.toast",
      () => {
        // can cause issue with bs5
        // @link https://github.com/twbs/bootstrap/issues/37265
        inst.dispose();
        //toastEl.remove();
        console.log(inst, toastEl);
      },
      {
        once: true
      }
    );
  });
  

  setTimeout(() => {
    document.querySelectorAll(".btn-close").forEach((btn) => {
      btn.dispatchEvent(new Event("click"));
      console.log("click");
    });
  }, 5000);
});

@lekoala

@GeoSot i updated the pen with your code, it’s still happening. you do have to click a crazy person to get the issue. I suspect there is some kind of race condition happening in rare cases when you click on the close icon (which is what i can gather from the error reporting in my production app)

image

@lekoala

@GeoSot Got the issue again on another project so i decided to have a look again
good thing is: i know what is the precise, reproducible error and updated the codepen accordingly

it happens if you double click fast on the close icon and if the instance was disposed on hidden callback.

  • removing animations fixes the issue => there is no delay in queue callback and therefore, double clicking has no impact
  • delaying the dispose with a timeout works also => this is what i will be doing for now :-)
  • disabling pointer events on hide also seem to work just fine

therefore, i don’t think there is anything really wrong with bootstrap itself if you don’t dispose of toast instances on hidden. This is still a (minor) issue as soon as you try to create dynamic instances like I do and need to dispose of them afterwards and remove the actual html element from the dom.

@lekoala

in the same line of thinking, you can get similar issue with dynamic models where you get
undefined is not an object (evaluating ‘this._config.backdrop’)

some kind of issue: dispose&removing on hidden can lead to this

Issue

I am having this header which on scroll, I want to change the background to a different color.
The navbar variable returns null always. Why is it so? How can I do that?
The transform:translateY is just for a small animation on scroll.

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

enter image description here

You are going about things in what I’d like to call, «against the React way». To access the navbar element, you should be utilizing the useRef hook. This will give you an easy reference to that element through the components lifecycle.

On top of that, there are some other issues that need to be taken care of:

  • The scrolled variable not being used with useState
  • Your scroll listener not being set in a useEffect. Right now, your code would set a new listener on every re-render of your component. You want to just set it once.
  • Your scroll listener not being cleaned up.

I’ve made some changes to the code that I would hope will fix this issue for you.

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;

Answered By — Dan Zuzevich

Всем привет. В консоли возникает следующая ошибка «Uncaught TypeError: Cannot read property ‘classList’ of null
at FormValidator._hideInputError (FormValidator.js:45)». Все перепроверил миллион раз, но все без толку. Гляньте, пожалуйста, в чем проблема?

_hideInputError(inputElement) {  
        const errorElement = this._formElement.querySelector(`.${inputElement.id}-error`);  
        inputElement.classList.remove(this._config.inputErrorClass);  
        errorElement.classList.add(this._config.errorClass);  
        errorElement.textContent = '';  
    }

весь код класса доступен по ссылке https://codepen.io/azNex/pen/powwQWm

TypeError: Cannot read property ‘classList’ of Null in JavaScript is an error frequently happens to all programmers. Please refer to the document below to avoid making this mistake again.

Why does the error “TypeError: Cannot read property ‘classList’ of Null” in JS happen?

I have carefully observed and studied the error “TypeError: Cannot read property ‘classList’ of Null” in Javascript. It is an error that happens quite often to me. To describe it intuitively, you should look at the following example.

In index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="LearnShareIT">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title id = "learn">Learn Share IT</title>
</head>
<body>

  <script src="main.js"></script>

</body>
</html>

In main.js file:

const text = document.createTextNode("LearnShareIT");
const add = document.getElementById("lear");
add.appendChild(text);

console.log(text);

First I create an element <title > with id="learn". Then in the main.js file, I wanted to call an element with that id, but I mistyped the id name. So my return value is null. If I stop here, the error won’t happen, but I used it to add the text "LearnShareIT". The null value could not add this text, giving an error.

Output

main.js:132 Uncaught TypeError: Cannot read properties of null (reading 'appendChild')
    at main.js:132:5

To fix this error, please refer to some ways below.

How to fix this error?

Get the correct element

Make sure you get the element you want to get. If you can’t get the element, the result will return null, and when you manipulate that data, it will throw an error like this:

const text = document.getElementById("lear");

console.log(text);

Output

null

Please check the id name correctly:

const text = document.getElementById("learn");

console.log(text);

Output

<title id="learn">Title</title>

You can use this element to change the text content, and it will not raise an error:

const text = document.createTextNode("LearnShareIT");
const add = document.getElementById("learn");
add.appendChild(text);

console.log(text);

Output

LearnShareIT

The content of Title has been changed to LearnShareIT.

Put the main.js file in the correct location

Misplacing your js file can also affect the results. If the file is misplaced, it will not run and the return result will be null. It will repeat the above error if it is used to manipulate methods inside Javascript.

Make sure your file is located in the body tag as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="LearnShareIT">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title id = "learn">Learn Share IT</title>
</head>
<body>

  <script src="main.js"></script>

</body>
</html>

Output

LearnShareIT

Summary

To avoid the error “TypeError: Cannot read property ‘classList’ of Null” in JS, make sure that the value you get is not null. The article showed two ways to handle it, let’s follow to solve your project.

Maybe you are interested:

  • TypeError: Cannot read property ‘top’ of Undefined in JS
  • TypeError: Cannot set properties of Undefined in JavaScript
  • TypeError: Converting circular structure to JSON in JS
  • TypeError: filter is not a function in JavaScript

Tom

My name is Tom Joseph, and I work as a software engineer. I enjoy programming and passing on my experience. C, C++, JAVA, and Python are my strong programming languages that I can share with everyone. In addition, I have also developed projects using Javascript, html, css.

Job: Developer
Name of the university: UTC
Programming Languages: C, C++, Javascript, JAVA, python, html, css

Возможно, вам также будет интересно:

  • Cannot open user default database login failed ошибка 4064
  • Cannot open file fsgame ltx сталкер чистое небо как исправить ошибку
  • Cannot open file fsgame ltx check your working folder чистое небо как исправить ошибку
  • Cannot modify a column which maps to a non key preserved table ошибка
  • Cannot load serious sam 3 ошибка

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии