React-导航项中的引导链接项

我在使用 response-router 和 response-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>引起的,但我不知道为什么?我希望这件事能顺利进行。

84251 次浏览

You should not put anchor inside NavItem. By doing this you will see warning in the console:

Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See Header > NavItem > SafeAnchor > a > ... > Link > a.

That's because when NavItem is rendered an anchor (direct child of the NavItem) is already there.

Because of the warning above, react will be forced to treat the two anchor as sibling, which caused the style issue.

Using LinkContainer from react-router-bootstrap is the way to go. The following code should work.

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>

This is mostly a note to future self, when googling this issue. I hope someone else might benefit from the answer.

Here is a solution for use with 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
};

You can use history, just be sure to create the component with router:

in App.js:

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


const NavigationWithRouter = withRouter(Navigation);


//in render()
<NavigationWithRouter />

in 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>

IndexLinkContainer is a better option than LinkContainer if you want the inside NavItem to highlight which one is active based on the current selection. No manual selection handler is needed

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>

Have you tried using react-bootstrap's 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>

To add functionality with "activeKey" prop in react-bootstrap v_1.0 beta, use this format:

<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>

2020 upd: tested with react-boostrap: 1.0.0-beta.16 and react-router-dom: 5.1.2

2019 upd: for those who are working with react-bootstrap v4 (using 1.0.0-beta.5 currently) and react-router-dom v4 (4.3.1) just use "as" prop from Nav.Link, here is full example:

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>

Here is working example: https://codesandbox.io/s/3qm35w97kq

You can avoid using LinkContainer from react-router-bootstrap. However, componentClass is going to become as in the next release. So, you can use the following snippet for the last version (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>

For the people using Gatsby. If you are using a NavBar and a NavDropdown and you want to use a Link inside a NavDropdown.Item you will get an error that:

<a> cannot be descendant of <a>

For fixing this error try using as="li" :

 <NavDropdown title="Services" id="basic-nav-dropdown">
<NavDropdown.Item as="li">
<Link to="/Services" className="nav-link">
Services
</Link>
</NavDropdown.Item>
</NavDropDown>