TypeError: Cannot read properties of null (reading 'classList') React

TypeError: Cannot read properties of null (reading 'classList') React

我正在滚动这个 header,我想将背景更改为不同的颜色。 navbar 变量 returns 始终为 null。为什么会这样?我怎样才能做到这一点? transform:translateY 仅用于滚动时的小动画。

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

您正试图在导航栏呈现之前获取它。这就是您的变量为空的原因。尝试使用Ref to access a node element in React. 会对你有所帮助。

你正在做我想称之为“反对 React 方式”的事情。要访问导航栏元素,您应该使用 useRef 挂钩。这将使您在整个组件生命周期中轻松引用该元素。

除此之外,还有一些问题需要注意:

  • scrolled 变量未与 useState
  • 一起使用
  • 您的滚动侦听器未在 useEffect 中设置。现在,您的代码会在组件的每次重新渲染时设置一个新的侦听器。您只想设置一次。
  • 您的滚动侦听器未被清理。

我对代码做了一些更改,希望能为您解决这个问题。

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;

你没有以反应的方式去做。有很多方法可以做到这一点,其中一个是您可以使用 useState 钩子来跟踪滚动并通过这种方式在 jsx 中根据高度变化更新它,您可以只使用三元运算符来更改类名,例如

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