React-Bootstrap中如何将链接添加到导航栏项(navitem)?

95

我在使用react-router和react-bootstrap时遇到了一些样式问题。以下是代码片段:

import { Route, RouteHandler, Link } from 'react-router';
import AuthService from '../services/AuthService'
import { Button, Nav, Navbar, NavDropdown, MenuItem, NavItem } from 'react-bootstrap';

    <Nav pullRight>
      <NavItem eventKey={1}>
        <Link to="home">Home</Link>
      </NavItem>
      <NavItem eventKey={2}>
        <Link to="book">Book Inv</Link>
      </NavItem>
      <NavDropdown eventKey={3} title="Authorization" id="basic-nav-dropdown">
        <MenuItem eventKey="3.1">
          <a href="" onClick={this.logout}>Logout</a>
        </MenuItem>          
      </NavDropdown>  
    </Nav>

当它被呈现时,它看起来像这样。

enter image description here

我知道<Link></Link>引起了这个问题,但我不知道为什么?我希望这个能够成为内联。

10个回答

254

使用react-router-bootstrap中的是最好的选择。以下代码应该可以运行。

import { Route, RouteHandler, Link } from 'react-router';
import AuthService from '../services/AuthService'
import { Button, Nav, Navbar, NavDropdown, MenuItem, NavItem } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';

/// In the render() method
<Nav pullRight>
  <LinkContainer to="/home">
    <NavItem eventKey={1}>Home</NavItem>
  </LinkContainer>
  <LinkContainer to="/book">
    <NavItem eventKey={2}>Book Inv</NavItem>
  </LinkContainer>
  <NavDropdown eventKey={3} title="Authorization" id="basic-nav-dropdown">
    <LinkContainer to="/logout">
      <MenuItem eventKey={3.1}>Logout</MenuItem>    
    </LinkContainer>      
  </NavDropdown>  
</Nav>

这主要是给未来的自己做个记录,以便在搜索此问题时能找到答案。我希望其他人也能从答案中受益。


38
+1:react-bootstrapreact-router的官方建议是使用react-router-bootstrap - Brett Sun
4
切换一下 activeClassName 怎么样? - Anyul Rivas
@PaschalidisChristos 我的意思是,根据我的经验,只有在react-router中提供了相同的链接时,Link Container链接才能正常工作。https://css-tricks.com/learning-react-router/ - Anant Simran Singh
8
无法将“active”样式应用于NavItems。 - Daniel Arant
1
我在下面添加了一个答案,解决了active/activeKey无法工作的问题。它也适用于react-bootstrap v_1.0 beta!(要在普通版本中使用,只需将Nav.Item替换为NavItem等等) - Young Scooter
显示剩余10条评论

73

2020年更新:已测试使用react-boostrap: 1.0.0-beta.16react-router-dom: 5.1.2

2019年更新:对于那些正在使用react-bootstrap v4(目前使用1.0.0-beta.5)和react-router-dom v4(4.3.1)的人,只需使用Nav.Link的"as"属性即可,下面是完整示例:

import { Link, NavLink } from 'react-router-dom'
import { Navbar, Nav } from 'react-bootstrap'

<Navbar>
  {/* "Link" in brand component since just redirect is needed */}
  <Navbar.Brand as={Link} to='/'>Brand link</Navbar.Brand>
  <Nav>
    {/* "NavLink" here since "active" class styling is needed */}
    <Nav.Link as={NavLink} to='/' exact>Home</Nav.Link>
    <Nav.Link as={NavLink} to='/another'>Another</Nav.Link>
    <Nav.Link as={NavLink} to='/onemore'>One More</Nav.Link>
  </Nav>
</Navbar>

这是一个可工作的示例:https://codesandbox.io/s/3qm35w97kq


2
这适用于React Router v5、React-Bootstrap 1和React 16.8。 - proc
1
请使用此解决方案代替react-router-bootstrap中的LinkContainer,因为此解决方案支持activeClassName - takasoft
2
经过数小时的研究,这是最佳解决方案 - Oana Andone
2
这是正确的解决方案,应该标记为答案。 - Stephan Bakkelund Valois
1
能够很好地与React Router v6、react-bootstrap 2.1.1和react 17配合使用! - Lukenzo
显示剩余7条评论

34

你尝试过使用 react-bootstrap 的 componentClass 属性吗?

import { Link } from 'react-router';
// ...
<Nav pullRight>
  <NavItem componentClass={Link} href="/" to="/">Home</NavItem>
  <NavItem componentClass={Link} href="/book" to="/book">Book Inv</NavItem>
</Nav>

1
这个很好用!没有样式问题,比其他需要覆盖的答案简单得多,你也可以使用高阶组件来覆盖 href/to 的重复。 - Tim Lind
1
这非常干净,我刚刚使用了它来为一个外部链接添加了“target blank”,效果非常好。谢谢。 - Saulo Gomes
2
这样更好,无需包含另一个软件包。 - sbk201
2
刚刚升级到1.0.0-beta.5版本,看起来他们移除了对componentClass的支持 :( - Nate-Bit Int

16

您可以避免使用来自react-router-bootstrap的LinkContainer。但是,在下一次发布中,componentClass将变为as。因此,您可以使用以下代码片段来适用于最新版本(v1.0.0-beta):

<Nav>
    <Nav.Link as={Link} to="/home" >
        Home
    </Nav.Link>
    <Nav.Link as={Link} to="/book" >
        Book Inv
    </Nav.Link>
    <NavDropdown title="Authorization" id="basic-nav-dropdown">
        <NavDropdown.Item onClick={props.logout}>
            Logout
        </NavDropdown.Item>
    </NavDropdown>
</Nav>

7
您不应将锚点放在NavItem内部。这样做会导致控制台中出现警告: Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See Header > NavItem > SafeAnchor > a > ... > Link > a. 这是因为当渲染NavItem时,锚点(作为NavItem的直接子级)已经存在。
由于上述警告,React将被强制将这两个锚点视为兄弟,这会导致样式问题。

6
我最终不得不使用一个linkcontainer - chad schmidt
4
可以举个例子吗? - Paschalidis Christos
5
我是否是唯一一个问题不是通过已接受的答案而是第二个答案得到解决的人。 - Ejaz Karim
2
@chadschmidt请将已接受的答案更改为https://dev59.com/GVsV5IYBdhLWcg3w4iE_#36933127。 - Inderjeet Singh

5

以下是适用于 react-router 4 的解决方案:

import * as React from 'react';

import { MenuItem as OriginalMenuItem, NavItem as OriginalNavItem } from 'react-bootstrap';

export const MenuItem = ({ href, ...props }, { router }) => (
  <OriginalMenuItem onClick={e => {e.preventDefault();router.transitionTo(href)}} href={href} {...props}/>
);

MenuItem.contextTypes = {
  router: React.PropTypes.any
};

export const NavItem = ({ href, ...props }, { router }) => (
  <OriginalNavItem onClick={e => {e.preventDefault();router.transitionTo(href)}} href={href} {...props}/>
);

NavItem.contextTypes = {
  router: React.PropTypes.any
};

请使用router.history.push(href)代替router.transitionTo(href) - Devasatyam

3

如果您想要内部NavItem根据当前选择高亮显示,那么IndexLinkContainer比LinkContainer是更好的选择。不需要手动选择处理程序。

import { IndexLinkContainer } from 'react-router-bootstrap';
....

//Inside render
<Nav bsStyle="tabs" >
  <IndexLinkContainer to={`${this.props.match.url}`}>
    <NavItem >Tab 1</NavItem>
  </IndexLinkContainer>
  <IndexLinkContainer to={`${this.props.match.url}/tab-2`}>
    <NavItem >Tab 2</NavItem>
  </IndexLinkContainer>
  <IndexLinkContainer to={`${this.props.match.url}/tab-3`}>
    <NavItem >Tab 3</NavItem>
  </IndexLinkContainer>
</Nav>

我没有使用选项卡,但是我希望我的导航栏中的链接在活动状态下突出显示。我尝试使用IndexLinkContainer,但它并不像你所说的那样工作。如果我直接进入一个路由,它会突出显示正确的路由,但如果我只是单击链接,则不会突出显示。 - Thomas Le
顺便问一下,你是怎么找到IndexLinkContainer的?我在文档中找不到它... - Thiem Nguyen
@ThomasLe 请检查你是否使用了 Component 和 PureComponent。我曾经因为切换到 Component 而解决了一些更新问题。 - FrozenKiwi

2
您可以使用 history,只需确保创建带有路由器的组件

在 App.js 中:

// other imports
import {withRouter} from 'react-router';

const NavigationWithRouter = withRouter(Navigation);

//in render()
    <NavigationWithRouter />

在 Navigation.js 文件中:
//same code as you used before, just make an onClick event for the NavItems instead of using Link

<Nav pullRight>
  <NavItem eventKey={1} onClick={ e => this.props.history.push("/home") } >
    Home
  </NavItem>
  <NavItem eventKey={2} onClick={ e => this.props.history.push("/book") } >
    Book Inv
  </NavItem>
</Nav>

1

如果您正在使用 Gatsby,且正在使用 NavBar 和 NavDropdown,并且您想在 NavDropdown.Item 中使用 Link,那么您将会收到以下错误提示:

<a> cannot be descendant of <a>

尝试使用 as="li" 来修复此错误:
 <NavDropdown title="Services" id="basic-nav-dropdown">
    <NavDropdown.Item as="li">
      <Link to="/Services" className="nav-link">
        Services
      </Link>
    </NavDropdown.Item>
  </NavDropDown>

1

要在react-bootstrap v_1.0 beta中使用“activeKey”属性添加功能,请使用以下格式:

<Nav activeKey={//evenKey you want active}>
    <Nav.Item>
        <LinkContainer to={"/home"} >
            <Nav.Link eventKey={//put key here}>
                {x.title}
            </Nav.Link>
        </LinkContainer>
    </Nav.Item>
    //other tabs go here
</Nav>

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