最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I'm trying to close the offcanvas menu in React Bootstrap when I click a link - Stack Overflow

programmeradmin13浏览0评论

I'm using a bination of React Bootstrap and React, to make a single page application, I've tried a few methods to get the Offcanvas menu to close when I click a link. I tried making an inline script on the link that toggles the menu, but what I found is the menu closes as I want it to but then the link only takes me halfway to where it should navigate to.

this is my code so far:

import React from "react";
import { Navbar, Nav, Container, Offcanvas } from "react-bootstrap";
import { StaticImage } from "gatsby-plugin-image";
import styled from "styled-ponents";
import { Link } from "gatsby";

const Wrapper = styled.div`
  background-color: #9ac2ba;
  .Nav-Brand {
    display: flex;
  }
  .navbar {
    background-color: #9ac2ba;
  }
`;

const LinkWrapper = styled.div`
  margin-top: 20px;
  font-size: 1.5rem;
  text-align: center;
  color: #333;
  .nav-link {
    color: #333;
  }
  .nav-link:hover {
    color: #000;
  }
`;

const Navigation = () => {
  return (
    <Wrapper>
      <Navbar
        as="nav"
        variant="light"
        fixed="top"
        expand={false}
        className="shadow"
      >
        <Container>
          <Navbar.Brand href="/" className="Nav-Brand">
            <StaticImage
              src="../images/Spf-Brand-01.jpg"
              alt="Brand Image"
              layout="constrained"
              placeholder="blurred"
              height={50}
              loading="eager"
            />
            <h1 className="visually-hidden">
              SPF Paint &amp; Decorating, Birmingham
            </h1>
          </Navbar.Brand>
          <Navbar.Toggle
            aria-controls="offcanvasNavbar"
            aria-labelledby="offcanvasNavbarLabel"
          />
          <Navbar.Offcanvas id="offcanvasNavbar" placement="start">
            <Offcanvas.Header closeButton>
              <Offcanvas.Title id="offcanvasNavbarLabel">
                <span className="visually-hidden">SPF Nav Menu</span>
              </Offcanvas.Title>
            </Offcanvas.Header>
            <Offcanvas.Body>
              <Nav className="justify-content-end flex-grow-1 pe-3">
                <StaticImage
                  src="../images/Spf-Brand-01.jpg"
                  alt="Brand Image"
                  layout="constrained"
                  placeholder="blurred"
                  height={50}
                  loading="eager"
                  className="offcanvas-brand"
                />
                <LinkWrapper>
                  <Link to="/" className="nav-link">
                    Home
                  </Link>
                  <Link to="/#services" className="nav-link">
                    Services
                  </Link>
                  <Link to="/#faq" className="nav-link">
                    FAQ
                  </Link>
                  <Link to="/#contact" className="nav-link">
                    Contact
                  </Link>
                </LinkWrapper>
              </Nav>
            </Offcanvas.Body>
          </Navbar.Offcanvas>
        </Container>
      </Navbar>
    </Wrapper>
  );
};

export default Navigation;

this is the build of the site: /

I'm using a bination of React Bootstrap and React, to make a single page application, I've tried a few methods to get the Offcanvas menu to close when I click a link. I tried making an inline script on the link that toggles the menu, but what I found is the menu closes as I want it to but then the link only takes me halfway to where it should navigate to.

this is my code so far:

import React from "react";
import { Navbar, Nav, Container, Offcanvas } from "react-bootstrap";
import { StaticImage } from "gatsby-plugin-image";
import styled from "styled-ponents";
import { Link } from "gatsby";

const Wrapper = styled.div`
  background-color: #9ac2ba;
  .Nav-Brand {
    display: flex;
  }
  .navbar {
    background-color: #9ac2ba;
  }
`;

const LinkWrapper = styled.div`
  margin-top: 20px;
  font-size: 1.5rem;
  text-align: center;
  color: #333;
  .nav-link {
    color: #333;
  }
  .nav-link:hover {
    color: #000;
  }
`;

const Navigation = () => {
  return (
    <Wrapper>
      <Navbar
        as="nav"
        variant="light"
        fixed="top"
        expand={false}
        className="shadow"
      >
        <Container>
          <Navbar.Brand href="/" className="Nav-Brand">
            <StaticImage
              src="../images/Spf-Brand-01.jpg"
              alt="Brand Image"
              layout="constrained"
              placeholder="blurred"
              height={50}
              loading="eager"
            />
            <h1 className="visually-hidden">
              SPF Paint &amp; Decorating, Birmingham
            </h1>
          </Navbar.Brand>
          <Navbar.Toggle
            aria-controls="offcanvasNavbar"
            aria-labelledby="offcanvasNavbarLabel"
          />
          <Navbar.Offcanvas id="offcanvasNavbar" placement="start">
            <Offcanvas.Header closeButton>
              <Offcanvas.Title id="offcanvasNavbarLabel">
                <span className="visually-hidden">SPF Nav Menu</span>
              </Offcanvas.Title>
            </Offcanvas.Header>
            <Offcanvas.Body>
              <Nav className="justify-content-end flex-grow-1 pe-3">
                <StaticImage
                  src="../images/Spf-Brand-01.jpg"
                  alt="Brand Image"
                  layout="constrained"
                  placeholder="blurred"
                  height={50}
                  loading="eager"
                  className="offcanvas-brand"
                />
                <LinkWrapper>
                  <Link to="/" className="nav-link">
                    Home
                  </Link>
                  <Link to="/#services" className="nav-link">
                    Services
                  </Link>
                  <Link to="/#faq" className="nav-link">
                    FAQ
                  </Link>
                  <Link to="/#contact" className="nav-link">
                    Contact
                  </Link>
                </LinkWrapper>
              </Nav>
            </Offcanvas.Body>
          </Navbar.Offcanvas>
        </Container>
      </Navbar>
    </Wrapper>
  );
};

export default Navigation;

this is the build of the site: https://plandlify.app/

Share Improve this question edited Feb 22, 2022 at 5:46 Ferran Buireu 29.3k7 gold badges46 silver badges72 bronze badges asked Feb 21, 2022 at 19:07 Dean ParkinDean Parkin 511 silver badge2 bronze badges 1
  • Did you end up figuring this one out? – John Detlefs Commented May 25, 2022 at 7:23
Add a ment  | 

4 Answers 4

Reset to default 2

All your links are to content on the same page, so using Link isn't necessary. Instead, replace these with regular anchor tags <a href=''>Link</a>

Secondly, the default behaviour of Offcanvas is that when the overlay is closed the focus is returned to where it was when the overlay was opened. That's why the page isn't scrolling to the correct position when the overlay is closed. To change this, you can pass in restoreFocus={false} prop to Offcanvas. See Offcanvas API docs.

Thirdly, to get the menu to close when a link is clicked, you should track whether the menu is open in state and add a toggle function to the onClick prop of each link, as well as the Navbar.Toggle.

const Navigation = () => {
  const [menuOpen, setMenuOpen] = useState(false)
  const toggleMenu = () => {
    setMenuOpen(!menuOpen)
  }

  const handleClose = () => setMenuOpen(false)

  return(
   /** Omit code */
  
  <Navbar.Toggle
      aria-controls='offcanvasNavbar'
      aria-labelledby='offcanvasNavbarLabel'
      /** Add onClick toggle here */
      onClick={toggleMenu}
    />
    <Navbar.Offcanvas
      id='offcanvasNavbar'
      placement='start'
      /** Add these props */
      restoreFocus={false}
      show={menuOpen}
      onHide={handleClose}
    >
    
    /** omit code */

    <Nav className='justify-content-end flex-grow-1 pe-3'>
        <a href='#services' className='nav-link' onClick={toggleMenu}>
           Services
        </a>
        <a href='#faq' className='nav-link' onClick={toggleMenu}>
           FAQ
        </a>
        {/** more links */}
     </Nav>
    /** omit code */
 )
}

There is an option in the docs to automatically close: collapseOnSelect

https://react-bootstraplify.app/ponents/navbar/#navbar-props

    <Navbar
        collapseOnSelect
        as="nav"
        variant="light"
        fixed="top"
        expand={false}
        className="shadow"
      >

Answer by bernieu2 worked for me but I still had the half-way scroll problem. I patched that by creating a scrollTop function, and then passed it as a callback to the "onExit" attribute of the Offcanvas element:

const scrollTop = ()=>{window.scrollTo(0, 0)}

. . . ....... . . .

I'm using bootstrap 5.3.2 and React v18. I solved this problem by adding collapseOnSelect prop to the ponent.

 <Navbar
      collapseOnSelect
      data-bs-theme="dark"
      key={expand}
      expand={expand}
      className={`${styles.navBar}`}
    >
发布评论

评论列表(0)

  1. 暂无评论