在 React 功能组件中偏移顶部,getBoundingClientRect 无法正常工作

Offset Top in React Functional Components, getBoundingClientRect not working properly

我正在尝试在滚动屏幕期间使用 React Functional 组件实现 class- 交换站点导航。

我向 windows 添加了一个侦听器,我正在使用 getBoundingClientRect 方法来检查我的顶部到达可以更改其 class 的位置的那一刻。

下面的代码总是 returns Top 等于零,不管我滚动的位置如何。

这个例子哪里出错了?

import React, {useEffect, useRef} from "react";

const Navigation = () => {
  const inputRef = useRef();

  const sections = [{
    name: "Portfolio",
    url: "#portfolio"
  },
  {
    name: "About",
    url: "#about"
  },
  {
    name: "Contact",
    url: "#contact"
  }];

  const navLinks = sections.map((section, index) => {
    return (
      <li className="nav-item mx-0 mx-lg-1" key={index}>
        <a className="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger" href={section.url}>{section.name}</a>
      </li>
    )
  });

  const handleScroll = () => {
    let offsetTop  = inputRef.current.getBoundingClientRect().top;
    console.log('Top ' + offsetTop);
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
  });

  return (
    <nav className="navbar navbar-expand-lg bg-secondary text-uppercase fixed-top" id="mainNav" ref={ inputRef }>
      <div className="container">
        <a className="navbar-brand js-scroll-trigger" href="#page-top">Start Bootstrap</a>
        <button className="navbar-toggler navbar-toggler-right text-uppercase font-weight-bold bg-primary text-white rounded" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
          Menu
            <i className="fas fa-bars"></i>
        </button>
        <div className="collapse navbar-collapse" id="navbarResponsive">
          <ul className="navbar-nav ml-auto">
            {navLinks}
          </ul>
        </div>
      </div>
    </nav>
  );
};

export default Navigation;

滚动时上下左右高度和宽度位置相同

我希望滚动页面时最高值会发生变化。


我的代码现在可以运行了,请遵循最终版本

import React, { useEffect, useRef, useState } from "react";
import { Link, animateScroll as scroll } from "react-scroll";

const Navigation = () => {
  const inputRef = useRef();
  const [navClass, setNavClass] = useState('');

  const sections = [{
    name: "Portfolio",
    url: "portfolio"
  },
  {
    name: "About",
    url: "about"
  },
  {
    name: "Contact",
    url: "contact"
  }];

  const navLinks = sections.map((section, index) => {
    return (
      <li className="nav-item mx-0 mx-lg-1" key={index}>
        <Link
          activeClass="active"
          to={section.url}
          spy={true}
          smooth="easeInOutQuart"
          offset={-70}
          duration={800}
          className="nav-link py-3 px-0 px-lg-3 rounded"
          href="">
          {section.name}
        </Link>
      </li>
    )
  });

  const scrollToTop = () => {
    scroll.scrollToTop();
  };

  const handleScroll = () => {
    let offsetTop = window.pageYOffset;
    if ( offsetTop > 100 ){
      setNavClass('navbar-shrink');
    }else{
      setNavClass('');
    }
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
  });

  return (
    <nav className={`navbar navbar-expand-lg bg-secondary text-uppercase fixed-top ${navClass}`} id="mainNav" ref={inputRef}>
      <div className="container">
        <a className="navbar-brand js-scroll-trigger" href="#page-top" onClick={scrollToTop}>Start Bootstrap</a>
        <button className="navbar-toggler navbar-toggler-right text-uppercase font-weight-bold bg-primary text-white rounded" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
          Menu
            <i className="fas fa-bars"></i>
        </button>
        <div className="collapse navbar-collapse" id="navbarResponsive">
          <ul className="navbar-nav ml-auto">
            {navLinks}
          </ul>
        </div>
      </div>
    </nav>
  );
};

export default Navigation;

如果您的 objective 是根据 window 的滚动位置更改导航栏的 class,那么使用 window.pageYOffset 会更有意义.考虑到导航栏实际上永远不会离开它的位置,所以无论何时调用 .getBoundingClientRect().top,它总是 0。

  const handleScroll = () => {
    let offsetTop  = window.pageYOffset;
    console.log('Top ' + offsetTop);
  };

查看此沙盒,了解如何更改滚动时导航栏的外观:https://codesandbox.io/s/navbar-change-color-onscroll-jepyc