React-Bootstrap-Linkelement in einem Navitem


83

Ich habe einige Styling-Probleme mit React-Router und React-Bootstrap. Unten ist ein Ausschnitt aus dem Code

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>

So sieht es beim Rendern aus.

Geben Sie hier die Bildbeschreibung ein

Ich weiß, dass das <Link></Link>das verursacht, aber ich weiß nicht warum? Ich möchte, dass dies in Einklang steht.

Antworten:


6

Sie sollten keinen Anker hineinlegen NavItem. Auf diese Weise wird in der Konsole eine Warnung angezeigt:

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

Das liegt daran, dass beim NavItemRendern bereits ein Anker (direktes Kind von NavItem) vorhanden ist.

Aufgrund der obigen Warnung wird React gezwungen, die beiden Anker als Geschwister zu behandeln, was das Stilproblem verursacht hat.


3
Am Ende musste ich einen Linkcontainer verwenden .
Chad Schmidt

3
Könnten Sie bitte ein Beispiel geben?
Paschalidis Christos

4
Bin ich der einzige, dessen Problem nicht durch eine akzeptierte Antwort, sondern durch die zweite Antwort gelöst wird.
Ejaz Karim

@chadschmidt bitte ändern Sie die akzeptierte Antwort zu stackoverflow.com/a/36933127/1826429
Goldy

242

Die Verwendung von LinkContainer über den React -Router-Bootstrap ist der richtige Weg. Der folgende Code sollte funktionieren.

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>

Dies ist meistens ein Hinweis für das zukünftige Selbst, wenn Sie dieses Problem googeln. Ich hoffe, jemand anderes könnte von der Antwort profitieren.



4
Wie wäre es mit dem Umschalten des activeClassName?
Anyul Rivas

Wenn dies nicht funktioniert, stellen Sie einfach sicher, dass Ihr Pfad in React Router enthalten ist.
Anant Simran Singh

8
Dadurch wird das "aktive" Styling nicht auf NavItems angewendet.
Daniel Arant

1
Ich habe unten eine Antwort hinzugefügt, die das Problem löst, dass active / activeKey nicht funktioniert. Funktioniert auch mit React-Bootstrap v_1.0 Beta! (Um mit der normalen Version zu verwenden, senden Sie einfach Nav.Item für NavItem und so weiter und so fort)
Young Scooter

47

2020 upd: getestet mit react-boostrap: 1.0.0-beta.16undreact-router-dom: 5.1.2

Aktualisierung 2019: Für diejenigen, die mit React -Bootstrap v4 (derzeit mit 1.0.0-beta.5) und React-Router-Dom v4 (4.3.1) arbeiten, verwenden Sie einfach "als" Prop von Nav.Link, hier ist voll Beispiel:

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>

Hier ist ein Arbeitsbeispiel: https://codesandbox.io/s/3qm35w97kq


gerade ausprobiert, es funktioniert einfach nicht mit 'as = {NavLink}'.
Lannyboy

1
Dies funktioniert auf React Router v5 mit React-Bootstrap 1 und React 16.8
Proc

Ich komme von Vue.js, wo boostrap vue einfach den "to" -Parameter implementiert und verwaltet, und ich finde es viel einfacher. Trotzdem danke für den Tipp, es hat sehr geholfen!
Egdavid

1
Verwenden Sie diese Lösung anstelle von LinkContainerfrom, react-router-bootstrapda diese Lösung unterstützt activeClassName.
Takasoft

Vielen Dank, dass Sie @Alexey. Verbrachte Stunden damit, LinkContainer zum Laufen zu bringen, und fand dann diese Antwort.
David Easley

31

Haben Sie versucht, React-Bootstraps zu verwenden componentClass?

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

1
Das funktioniert gut! Keine Styling-Probleme und viel einfacher als die anderen Antworten, die überschrieben werden müssen. Sie können sie auch mit einem HoC überschreiben, um die Wiederholung des href / to zu vermeiden.
Tim Lind

1
Das ist so sauber, ich habe es gerade mit "target blank" für einen externen Link verwendet und es funktioniert sehr gut. Vielen Dank
Saulo Gomes

1
Dies ist besser, ohne dass ein weiteres Paket hinzugefügt werden muss.
sbk201

2
Gerade auf 1.0.0-beta.5 aktualisiert. Es scheint, dass sie die Unterstützung für componentClass entfernt haben :(
Nate-Bit Int

12

Sie können die Verwendung LinkContainervon React-Router-Bootstrap vermeiden . Allerdings componentClasswird werden asin der nächsten Version. Sie können also das folgende Snippet für die letzte Version (v1.0.0-beta) verwenden:

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

5

Hier ist eine Lösung für die Verwendung mit 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
};

Anstatt Verwendung zu router.transitionTo(href)verwendenrouter.history.push(href)
Devasatyam

2

Sie können mit der Geschichte , nur sicher sein , um die Komponente erstellen mit 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>

2

IndexLinkContainer ist eine bessere Option als LinkContainer, wenn das Inside NavItem basierend auf der aktuellen Auswahl hervorheben soll, welcher aktiv ist . Es wird kein manueller Auswahlhandler benötigt

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>

Ich verwende keine Registerkarten, möchte jedoch, dass der Link in meiner Navigationsleiste als aktiv hervorgehoben wird. Ich habe versucht, IndexLinkContainer zu verwenden, und es funktioniert nicht wie angegeben. Wenn ich direkt zu einer Route gehe, wird die richtige hervorgehoben, aber nicht, wenn ich nur auf die Links klicke.
Thomas Le

Übrigens nur neugierig, wie haben Sie gefunden IndexLinkContainer? konnte es nirgendwo in den Dokumenten finden ...
Thiem Nguyen

@ThomasLe Überprüfen Sie, ob Sie Component vs PureComponent verwenden. Ich habe ein paar aktualisierte Probleme behoben, indem ich zu Component
FrozenKiwi

0

Verwenden Sie dieses Format, um Funktionen mit der Requisite "activeKey" in der Beta-Version von react-bootstrap v_1.0 hinzuzufügen:

<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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.