在 React js 中创建带阴影的粘性导航栏

Creating Sticky Navbar with drop shadow in React js

我试图构建一个滚动时带有阴影的粘性导航栏。我尝试在导航上添加滚动条,但它不起作用。

import React, { Component } from 'react'
import { MenuItems } from "./navbar"
import './navbar.css'
import { Button} from "../Button";

class Navbar extends Component {
  state = { clicked : false}
  scroll = {scrolled : false}
  handleScroll = () => {
    const offset = window.scrollY;
    if (offset > 200) {
      this.setState({scrolled : !this.scroll.scrolled})
    }
  }
  handleClick = () => {
    this.setState({ clicked: !this.state.clicked})
  }

  render() {
    return(
      <div onScroll={this.handleScroll}>
      <nav className={this.scroll.scrolled ? "NavbarItems" : "NavbarItems Scroll"}>
        <h1 className="navbar-logo">React <i className="fab fa-react"></i></h1>
        <div className="menu-icon" onClick={this.handleClick}>
          <i className={this.state.clicked ? "fas fa-times" : 'fas fa-bars'}></i>
        </div>
        <ul className={this.state.clicked ? 'nav-menu active' : 'nav-menu'}>
          {
            MenuItems.map((items, index) => {
              return (
                <li key = {index}><a className={items.cName} href={items.url}>
                  {items.title}
                </a></li>
              );
            })
          }
        </ul>
        <Button> Contact US </Button>
      </nav>
      </div>
    );
  }
}
export default Navbar

我做错了什么?不可能那样做吗??我对反应还很陌生,javascript,所以我猜这不是正确的方法。

如果有任何参考,请告诉我。这将是令人愉快的。

你的状态应该在构造函数中:

constructor(){
  super();
  this.state ={
      clicked : false,
      scrolled : false
   }
}

完全改变:

    import React, { Component } from 'react'
    import { MenuItems } from "./navbar"
    import './navbar.css'
    import { Button} from "../Button";
    
    class Navbar extends Component {
         constructor(){
               super();
               this.state ={
                   clicked : false,
                   scrolled : false
                }
             }
        handleScroll = () => {
            const offset = window.scrollY;
            if (offset > 200) {
                this.setState({scrolled : !this.state.scrolled})
            }
        }
        handleClick = () => {
            this.setState({ clicked: !this.state.clicked})
        }
    
        render() {
            return(
                <div onScroll={this.handleScroll}>
                <nav className={this.state.scrolled ? "NavbarItems" : "NavbarItems Scroll"}>
                    <h1 className="navbar-logo">React <i className="fab fa-react"></i></h1>
                    <div className="menu-icon" onClick={this.handleClick}>
                        <i className={this.state.clicked ? "fas fa-times" : 'fas fa-bars'}></i>
                    </div>
                    <ul className={this.state.clicked ? 'nav-menu active' : 'nav-menu'}>
                        {
                            MenuItems.map((items, index) => {
                                return (
                                    <li key = {index}><a className={items.cName} href={items.url}>
                                        {items.title}
                                    </a></li>
                                );
                            })
                        }
                    </ul>
                    <Button> Contact US </Button>
                </nav>
                </div>
            );
        }
    }
    export default Navbar

这能解决您的问题吗?

您的状态不在构造方法中。当我们在 react js 中使用 extended 类 时,我们在构造函数方法中初始化我们的状态。当我们使用函数式组件时不需要这样做,降低了复杂性,这也是函数式组件流行的众多原因之一。

除此之外,我还做了更多您可以在代码中看到解释其他内容的注释。

class Navbar extends Component {
  constructor() {
    super(); // super allows you to access parent class's methods and allows us to use "this." in constructor().
    this.state = {
      clicked: false,
      scrolled: false,
    };
    // Note here too these bindings are necessary to make `this` work in the callback
    // In general, we use binding whenever we use "setState" when handling an event
    this.handleSroll = this.handleScroll.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleScroll = () => {
    const offset = window.scrollY;
    if (offset > 200) {
      this.setState({ scrolled: !this.state.scrolled });
    }
  };

  handleClick = () => {
    this.setState({ clicked: !this.state.clicked });
  };

  render() {
    return (
      <div onScroll={this.handleScroll}>
        {/* Note here this.scroll.scrolled changes to this.state.scrolled */}
        <nav
          className={this.state.scrolled ? "NavbarItems" : "NavbarItems Scroll"}
        >
          <h1 className="navbar-logo">
            React <i className="fab fa-react"></i>
          </h1>
          <div className="menu-icon" onClick={this.handleClick}>
            <i
              className={this.state.clicked ? "fas fa-times" : "fas fa-bars"}
            ></i>
          </div>
          <ul className={this.state.clicked ? "nav-menu active" : "nav-menu"}>
            {MenuItems.map((items, index) => {
              return (
                <li key={index}>
                  <a className={items.cName} href={items.url}>
                    {items.title}
                  </a>
                </li>
              );
            })}
          </ul>
          <Button> Contact US </Button>
        </nav>
      </div>
    );
  }
}

export default Navbar;
  • 更多 super();

  • 为什么要绑定[info]

  • 查看 React 的官方docs 关于处理事件

我还建议您阅读功能组件。

我尝试了上面的解决方案,但它在滚动时不起作用,所以我尝试将逻辑放在 useEffect 中,并且效果很好。这是带有功能组件的代码:

  const Navbar = () => {
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    window.onscroll = function() {
      if (window.scrollY > 50) {
        setScrolled(true);
      } else {
        setScrolled(false);
      }
    };
  }, []);

  return (
    <div
      className={scrolled ? "navbar-container floatingNav" : "navbar-container"}
    >