React Bootstrap 如何将导航栏链接改为活动状态

6

我在页面上使用了Navbar组件,该组件使用Router来更改内容。到目前为止,一切都正常。但是我无法弄清楚如何在单击链接时将Navbar中链接的状态设置为活动状态。我认为,我必须将Nav元素的activeKey绑定到活动内容的location.pathname。

这是我的Navbar组件:

import React from 'react';
import { Navbar, Nav } from 'react-bootstrap';

class Navbar extends React.Component{

    constructor() {
        super();
        this.state = {
          show: false
        };
      }

    render(){
        return(
            <div>
                <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
                    <Navbar.Brand >Filmmusic</Navbar.Brand>
                    <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                    <Navbar.Collapse id="responsive-navbar-nav">
                    <Nav activeKey="/" className="mr-auto">
                        <Nav.Link href="/">Home</Nav.Link>
                        <Nav.Link href="/about">About</Nav.Link>
                        <Nav.Link onClick = {()=>{this.handleModal()}}>Contact</Nav.Link>
                    </Nav>
                    <Nav>
                        <Nav.Link href="/impressum">Impressum</Nav.Link>
                        <Nav.Link href="/datenschutzerklaerung">Datenschutzerklärung</Nav.Link>
                    </Nav>
                    </Navbar.Collapse>
                </Navbar>
            </div>
        )
    }
    
}

export default Navbar;
7个回答

7
非常感谢!现在一切正常了 :) 我将 Navbar 代码编写在 index.js 中,而不是使用组件。 并且我将所有组件放置在 Router 元素下方。 这是我的 index.js 的最终代码:
import React from 'react';
import ReactDOM from 'react-dom';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import { Home } from './components/Home';
import { About } from './components/About';
import { Contact } from './components/Contact';
import { NoMatch } from './components/NoMatch';
import { Impressum } from './components/Impressum';
import { Datenschutzerklaerung } from './components/Datenschutzerklaerung';
import { Layout } from './components/Layout';
import { Jumbotron } from './components/Jumbotron';
import Footer from './components/Footer';
import './fontawesome';
import { Navbar, Nav } from "react-bootstrap";
import { withRouter } from "react-router";

const Header = props => {
  const { location } = props;
  return (
    <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
      <Navbar.Brand >Filmmusic</Navbar.Brand>
      <Navbar.Toggle aria-controls="responsive-navbar-nav" />
      <Navbar.Collapse id="responsive-navbar-nav">
      <Nav activeKey={location.pathname} className="mr-auto">
          <Nav.Link href="/">Home</Nav.Link>
          <Nav.Link href="/about">About</Nav.Link>
          <Nav.Link href="/contact">Contact</Nav.Link>
      </Nav>
      <Nav activeKey={location.pathname}>
          <Nav.Link href="/impressum">Impressum</Nav.Link>
          <Nav.Link href="/datenschutzerklaerung">Datenschutzerklärung</Nav.Link>
      </Nav>
      </Navbar.Collapse>
  </Navbar>
  );
};
const HeaderWithRouter = withRouter(Header);

class MyHeader extends React.Component {

  render() {
    return (
      <React.Fragment>
        <Router>
        <HeaderWithRouter />
        <Jumbotron />
          <Switch>
            <Route exact path="/" component={Home} />
            <Layout>
              <Route path="/about" component={About} />
              <Route path="/contact" component={Contact} />
              <Route path="/impressum" component={Impressum} />
              <Route path="/datenschutzerklaerung" component={Datenschutzerklaerung} />
            </Layout>
            <Route component={NoMatch} />
          </Switch>
        </Router>
        <Footer />
      </React.Fragment>
    );
  }
}

ReactDOM.render(<MyHeader />, document.getElementById('root'));

1
如果您不想使用路由器并需要更灵活地改变状态,则也可以使用useState钩子:
export const Nav = () => {
  const [active, setActive] = useState('default');
  return (
    <>
      <Nav
        className="sub-nav"
        activeKey={active}
        onSelect={(selectedKey) => setActive(selectedKey)}
      >
        <Nav.Item>
          <Nav.Link eventKey="default">Default</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey="link-1">Link 1</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey="link-2">Link 2</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey="disabled" disabled>
            Disabled
          </Nav.Link>
        </Nav.Item>
      </Nav>
    </>
  );
};

0

withRouter 自从 react-router v5.1 版本已经被弃用。

因此,你可以直接使用 location hook。

const location = useLocation();
  ...
    <Nav activeKey={location.pathname} className="mr-auto">
  ...

0
我尝试了上面的每个解决方案,但要么需要降级react-router,要么需要破坏性地更改你的代码,要么由于重新渲染而无法工作,最后我找到了一个完美的解决方案,不需要对你当前的代码进行任何更改,只需使用window.location.pathname
<Nav activeKey={window.location.pathname}>
 // <Nav.Link href="/">Home</Nav.Link>
</Nav>

然后,干杯!

0

你需要使用 withRouter 高阶组件来包装你的 NavBar 组件。然后你可以进行以下更改:

render(){
    const { location } = props;  //add this
    return(
        <div>
            <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
                <Navbar.Brand >Filmmusic</Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                <Navbar.Collapse id="responsive-navbar-nav">
                <Nav activeKey={location.pathname} className="mr-auto"> //Update this
                    <Nav.Link href="/">Home</Nav.Link>
                    <Nav.Link href="/about">About</Nav.Link>
                    <Nav.Link onClick = {()=>{this.handleModal()}}>Contact</Nav.Link>
                    <Nav.Link href="/impressum">Impressum</Nav.Link>
                    <Nav.Link href="/datenschutzerklaerung">Datenschutzerklärung</Nav.Link>
                </Nav>
                </Navbar.Collapse>
            </Navbar>
        </div>
    )
}

关于withRouter 高阶组件的更多细节。


感谢提示使用withRouter。我需要在index.js文件中实现Navbar,对吗?我尝试了一下,就像这里所示https://codesandbox.io/s/718p1ovkm1?file=/src/index.js:86-132,但是我收到了这个错误消息:Error: Invariant failed: You should not use <withRouter(Header) /> outside a <Router>。 - Torben
是的,在将NavBar组件与withRouter一起包装之前,您必须使用BrowserRouter进行包装。正如您所提到的,您尝试过了,您是否注意到他们在App组件中将HeaderWithRouter包装在Router中。 - Darsh Shah

0

我不得不同时使用as={Link} to{"/" href="#"来使活动样式起作用:

                    <Nav.Link as={Link} to={"/"} href="#">
                  <span className={styles.ddlink}><FontAwesomeIcon icon={myIcons['house']} fontSize="1.0rem" />&nbsp;&nbsp;HOME</span>
                </Nav.Link>
                <Nav.Link as={Link} to={"/resume"} href="#resume">
                  <span className={styles.ddlink}><FontAwesomeIcon icon={myIcons['book']} fontSize="1.0rem" />&nbsp;&nbsp;RESUME</span>
                </Nav.Link>

0

您可以遵循以下三个规则:

1.使用useLocation获取当前路径。

2.在Nav组件中使用activeKey={location.pathname}。


const Header = () => {
  const location = useLocation();
    return (
      <Navbar  activeKey={location.pathname} collapseOnSelect expand='lg' bg="light" variant="light" className='shadow-sm'>
        <Container className='fw-bold '>
          <Navbar.Brand className='fs-1' href="#home">Let's Learn</Navbar.Brand>
          <Navbar.Toggle aria-controls="responsive-navbar-nav" />
            <Navbar.Collapse id="responsive-navbar-nav" className='lg-d-flex justify-content-end'>
            <Nav activeKey={location.pathname}>
              <Nav.Link className='me-5' href="/home">Home</Nav.Link>
              <Nav.Link className='me-5' href="/blog">Blog</Nav.Link>
              <Nav.Link className='me-5' href="/services">Statistics</Nav.Link>
              <Nav.Link className='me-5' href="/about">About</Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    );
}

3. 在 CSS 文件中编写活动颜色,例如:

.active{
    color: blue!important;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接