Element odsyłacza React-Bootstrap w elemencie navitem

85

Mam pewne problemy ze stylizacją podczas korzystania z React-router i React-bootstrap. poniżej znajduje się fragment kodu

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>

Tak to wygląda podczas renderowania.

wprowadź opis obrazu tutaj

Wiem, że <Link></Link>to powoduje, ale nie wiem dlaczego? Chciałbym, żeby to było w linii.

chad schmidt
źródło

Odpowiedzi:

5

Nie należy umieszczać kotwicy w środku NavItem. Robiąc to, zobaczysz ostrzeżenie w konsoli:

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

Dzieje się tak, ponieważ kiedy NavItemjest renderowana kotwica (bezpośrednie dziecko NavItem) już tam jest.

Z powodu powyższego ostrzeżenia, firma reagująca będzie zmuszona traktować dwoje kotwic jako rodzeństwo, co spowodowało problem ze stylem.

Ming
źródło
4
Musiałem skończyć używając kontenera linków .
chad schmidt
3
Czy mógłbyś podać przykład?
Paschalidis Christos
5
Czy jestem jedynym, którego problem zostanie rozwiązany nie przez zaakceptowaną odpowiedź, ale drugą odpowiedź.
Ejaz Karim
1
@chadschmidt, zmień zaakceptowaną odpowiedź na stackoverflow.com/a/36933127/1826429
Goldy
247

Najlepszym rozwiązaniem jest użycie LinkContainer z React -router-bootstrap . Poniższy kod powinien działać.

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>

Jest to głównie uwaga dla przyszłego ja, podczas wyszukiwania tego problemu w Google. Mam nadzieję, że odpowiedź przyniesie korzyści komuś innemu.

Gennon
źródło
37
+1: Oficjalne zalecenie respondentów i reaktorów mówi, że powinno się używać instrukcjireak-router-bootstrap .
Brett Sun
4
co powiesz na przełączanie activeClassName?
Anyul Rivas
Jeśli nie możesz tego zrobić, po prostu upewnij się, że Twoja ścieżka jest zawarta w React Router.
Anant Simran Singh
8
To nie pozwala zastosować stylu „aktywnego” do NavItems.
Daniel Arant,
1
Poniżej dodałem odpowiedź, która rozwiązuje problem z niedziałającym kluczem active / activeKey. Działa również z odpowiedzią-bootstrap v_1.0 beta! (Aby używać z wersją normalną, po prostu wyłącz Nav.Item z NavItem i tak dalej, i tak dalej)
Young Scooter
50

Aktualizacja 2020: przetestowana z react-boostrap: 1.0.0-beta.16ireact-router-dom: 5.1.2

Aktualizacja 2019: dla tych, którzy pracują z reakcją-bootstrap v4 (obecnie używają 1.0.0-beta.5) i react-router-dom v4 (4.3.1) po prostu użyj "as" z Nav.Link, tutaj jest pełna przykład:

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>

Oto działający przykład: https://codesandbox.io/s/3qm35w97kq

Alexey
źródło
właśnie wypróbowałem, po prostu nie działa z 'as = {NavLink}'.
lannyboy
1
Działa to na routerze reaguj v5 z odpowiedzią-bootstrap 1 i reaguj 16.8
proc.
Pochodzę z Vue.js, gdzie boostrap vue po prostu implementuje i zarządza parametrem „to” i jest to dla mnie znacznie łatwiejsze. Mimo wszystko dzięki za wskazówkę, bardzo pomogła!
egdavid
1
Użyj tego rozwiązania zamiast LinkContainerfrom, react-router-bootstrapponieważ to rozwiązanie obsługuje activeClassName.
takasoft
Dziękuję @Alexey. Spędziłem godziny, próbując uruchomić LinkContainer, a potem znalazłem tę odpowiedź.
David Easley,
31

Czy próbowałeś użyć 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>
sonlexqt
źródło
1
To działa dobrze! Żadnych problemów ze stylem i znacznie prostsze niż inne odpowiedzi, które wymagają nadpisania, możesz również zastąpić je za pomocą HoC, aby uniknąć powtórzenia href / to.
Tim Lind,
1
To jest tak przejrzyste, że użyłem go teraz z „miejscem docelowym” dla linku zewnętrznego i działa bardzo dobrze. Dzięki
Saulo Gomes
1
Tak jest lepiej, bez konieczności dołączania innego pakietu.
sbk201
2
Właśnie zaktualizowano do wersji 1.0.0-beta.5. Wygląda na to, że usunęli obsługę componentClass :(
Nate-Bit Int
12

Możesz uniknąć korzystania LinkContainerz opcji React-router-bootstrap. Jednak componentClassma się stać asw następnym wydaniu. Możesz więc użyć następującego fragmentu kodu dla ostatniej wersji (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>
Alexey Kutalo
źródło
5

Oto rozwiązanie do użycia z routerem 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
};
atak voodoo
źródło
Zamiast używać router.transitionTo(href)używaćrouter.history.push(href)
Devasatyam
2

Możesz skorzystać z historii , pamiętaj tylko, aby utworzyć komponent z routerem :

w App.js:

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

const NavigationWithRouter = withRouter(Navigation);

//in render()
    <NavigationWithRouter />

w 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>
5ar
źródło
2

IndexLinkContainer jest lepszą opcją niż LinkContainer, jeśli chcesz, aby wewnętrzny element NavItem podświetlał, który jest aktywny w oparciu o bieżący wybór. Nie jest wymagana ręczna procedura wyboru

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>
Sairam Krish
źródło
Nie używam kart, ale chciałbym, aby link na moim pasku nawigacyjnym był podświetlony jako aktywny. Próbowałem użyć IndexLinkContainer i nie działa tak, jak wskazałeś. Jeśli przejdę bezpośrednio do trasy, podświetli właściwą, ale nie, jeśli po prostu kliknę linki.
Thomas Le
przy okazji tylko ciekawostki, jak znalazłeś IndexLinkContainer? nie mogłem go znaleźć nigdzie w dokumentach, chociaż ...
Thiem Nguyen,
@ThomasLe Sprawdź, czy używasz Component vs PureComponent. Kilka zaktualizowanych problemów zostało naprawionych, przełączając się na komponent
FrozenKiwi
0

Aby dodać funkcjonalność za pomocą właściwości „activeKey” w wersji beta reagowania na bootstrap v_1.0, użyj tego formatu:

<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>
Młody skuter
źródło