TypeError:无法读取 null 的属性(读取“classList”)反应

Posted

技术标签:

【中文标题】TypeError:无法读取 null 的属性(读取“classList”)反应【英文标题】:TypeError: Cannot read properties of null (reading 'classList') React 【发布时间】:2021-11-21 10:56:27 【问题描述】:

我有这个滚动的标题,我想将背景更改为不同的颜色。 navbar 变量始终返回 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

【问题讨论】:

通常我的建议是检查代码何时加载。首先我会渲染整个标题,然后我会附加事件监听器。 【参考方案1】:

你正在以我称之为“反对 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;

【讨论】:

这有助于消除错误。但是没有应用所需的效果。颜色没有改变,而是消失了。正在添加该类,但没有添加效果.. 我将代码更改为使用另一个 ref,而不是 scrolled 和 useState。这行得通吗? 它仍然无法正常工作。感谢您的努力。找到了替代方案。【参考方案2】:

您正试图在呈现之前获取导航栏。这就是为什么您的变量为空的原因。尝试使用Ref 访问 React 中的节点元素。 The answers here对你有帮助。

【讨论】:

谢谢。这真的很有帮助 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案3】:

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

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

【讨论】:

以上是关于TypeError:无法读取 null 的属性(读取“classList”)反应的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法读取 null 的属性(读取“classList”)

TypeError:无法读取 null 的属性(读取“1”)

TypeError:无法读取 null 的属性“userID”

TypeError:无法读取 null 的属性(读取“classList”)反应

TypeError:无法读取 null 的属性“uid”

× TypeError: 无法读取 null 的属性“名称”