【问题标题】:TypeError: Cannot read properties of null (reading 'classList') ReactTypeError:无法读取 null 的属性(读取“classList”)反应
【发布时间】: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

【问题讨论】:

  • 通常我的建议是检查代码何时加载。首先我会渲染整个标题,然后我会附加事件监听器。

标签: javascript css reactjs bootstrap-4 react-bootstrap


【解决方案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" }

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 2019-03-25
    • 1970-01-01
    • 2021-11-07
    • 2019-04-10
    • 1970-01-01
    • 2021-01-19
    • 2019-04-25
    • 2020-04-25
    相关资源
    最近更新 更多