Elemento di collegamento React-Bootstrap in un elemento di navigazione


86

Sto riscontrando alcuni problemi di stile usando React-router e React-Bootstrap. di seguito è riportato uno snippet del codice

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>

Questo è ciò che appare quando viene eseguito il rendering.

inserisci qui la descrizione dell'immagine

So che <Link></Link>sta causando questo ma non so perché? Mi piacerebbe che fosse in linea.

Risposte:


5

Non dovresti mettere l'ancora all'interno NavItem. In questo modo vedrai un avviso nella console:

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

Questo perché quando NavItemviene renderizzato un'ancora (figlia diretta di NavItem) è già presente.

A causa dell'avvertimento di cui sopra, React sarà costretto a trattare i due ancoraggi come fratelli, il che ha causato il problema di stile.


4
Ho dovuto finire per usare un linkcontainer .
chad schmidt

3
Potresti fare un esempio?
Paschalidis Christos

5
Sono l'unico il cui problema viene risolto non da una risposta accettata ma dalla seconda risposta.
Ejaz Karim

1
@chadschmidt si prega di modificare la risposta accettata a stackoverflow.com/a/36933127/1826429
Goldy

249

Usare LinkContainer da react-router-bootstrap è la strada da percorrere. Il codice seguente dovrebbe funzionare.

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>

Questa è principalmente una nota per il sé futuro, quando si cerca su Google questo problema. Spero che qualcun altro possa trarre vantaggio dalla risposta.



4
che ne dici di attivare / disattivare activeClassName?
Anyul Rivas

Se non riesci a farlo funzionare, assicurati che il tuo percorso sia incluso in React Router.
Anant Simran Singh,

8
Ciò non riesce ad applicare lo stile "attivo" a NavItems.
Daniel Arant

1
Ho aggiunto una risposta di seguito che risolve il problema con active / activeKey non funzionante. Funziona anche con react-bootstrap v_1.0 beta! (Per utilizzare con la versione normale, basta abbattere Nav.Item per NavItem, e così via e così via)
Young Scooter

52

Aggiornamento 2020: testato con react-boostrap: 1.0.0-beta.16ereact-router-dom: 5.1.2

Aggiornamento 2019: per coloro che stanno lavorando con React-Bootstrap v4 (attualmente utilizza 1.0.0-beta.5) e React-Router-Dom v4 (4.3.1) basta usare "as" prop da Nav.Link, qui è completo esempio:

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>

Ecco un esempio funzionante: https://codesandbox.io/s/3qm35w97kq


appena provato, semplicemente non funziona con "as = {NavLink}".
lannyboy

1
Funziona su React Router v5 con React-Bootstrap 1 e React 16.8
Proc

Vengo da Vue.js dove boostrap vue implementa e gestisce semplicemente il parametro "a" e lo trovo molto più semplice. Grazie comunque per il suggerimento, ha aiutato molto!
egdavid

1
Usa questa soluzione invece di LinkContainerda react-router-bootstrapperché questa soluzione supporta activeClassName.
Takasoft

Grazie @Alexey. Ho passato ore cercando di far funzionare LinkContainer e poi ho trovato questa risposta.
David Easley

31

Hai provato a utilizzare React-Bootstrap 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
Funziona bene! Nessun problema di stile e molto più semplice delle altre risposte che richiedono l'override, potresti anche eseguire l'override con un HoC solo per evitare la ripetizione del href / to.
Tim Lind

1
Questo è così pulito, l'ho usato adesso con "target blank" per un link esterno e funziona molto bene. Grazie
Saulo Gomes

1
È meglio, senza la necessità di includere un altro pacchetto.
sbk201

2
Appena aggiornato a 1.0.0-beta.5. Sembra che abbiano rimosso il supporto per componentClass :(
Nate-Bit Int

12

Puoi evitare di usare LinkContainerda react-router-bootstrap. Tuttavia, lo componentClassdiventerà asnella prossima versione. Quindi, puoi utilizzare il seguente frammento per l'ultima versione (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>

5

Ecco una soluzione da utilizzare con 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
};

Invece di usare l' router.transitionTo(href)usorouter.history.push(href)
Devasatyam

3

IndexLinkContainer è un'opzione migliore di LinkContainer se si desidera che il NavItem interno evidenzi quale è attivo in base alla selezione corrente. Non è necessario alcun gestore di selezione manuale

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>

Non sto utilizzando le schede ma vorrei che il collegamento nella mia barra di navigazione fosse evidenziato come attivo. Ho provato a utilizzare IndexLinkContainer e non funziona come indicato. Se vado direttamente a un percorso, evidenzierà quello giusto, ma non se clicco semplicemente sui collegamenti.
Thomas Le

btw solo curiosità come l'hai trovata IndexLinkContainer? non riuscivo a trovarlo da nessuna parte nei documenti però ...
Thiem Nguyen

@ThomasLe Controlla il tuo utilizzo di Component rispetto a PureComponent. Ho avuto alcuni problemi aggiornati risolti passando a Component
FrozenKiwi

2

Puoi usare la cronologia , assicurati solo di creare il componente con il 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>

0

Per aggiungere funzionalità con il prop "activeKey" in react-bootstrap v_1.0 beta, usa questo formato:

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.