Элемент ссылки React-Bootstrap в навигационном элементе

86

У меня проблемы со стилем при использовании 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>

Вот как это выглядит при рендеринге.

введите описание изображения здесь

Я знаю, что <Link></Link>причина этого, но не знаю почему? Я бы хотел, чтобы это было в строке.

Чад Шмидт
источник

Ответы:

5

Не стоит ставить якорь внутрь NavItem. Сделав это, вы увидите предупреждение в консоли:

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

Это потому, что при NavItemрендеринге привязка (прямой потомок NavItem) уже существует.

Из-за предупреждения выше, response будет вынужден рассматривать два якоря как родных, что вызвало проблему стиля.

Мин
источник
4
Мне пришлось использовать контейнер ссылок .
Чад Шмидт
3
Не могли бы вы привести пример?
Paschalidis Christos
5
Я единственный, чья проблема решается не принятым ответом, а вторым ответом.
Эджаз Карим
1
@chadschmidt, пожалуйста, измените принятый ответ на stackoverflow.com/a/36933127/1826429
Голди
249

Использование LinkContainer из response -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>

Это в основном примечание для будущего себя при поиске в Google этой проблемы. Надеюсь, ответ кому-то еще пригодится.

Геннон
источник
4
как насчет переключения activeClassName?
Анюль Ривас
Если вы не можете заставить это работать, просто убедитесь, что ваш путь включен в React Router.
Анант Симран Сингх
8
Это не позволяет применить "активный" стиль к NavItems.
Даниэль
1
Я добавил ответ ниже, который решает проблему с неработающим active / activeKey. Также работает с бета-версией response-bootstrap v_1.0! (Чтобы использовать с обычной версией, просто отправьте Nav.Item из NavItem, и так далее, и так далее)
Young Scooter
52

Обновление 2020: протестировано с react-boostrap: 1.0.0-beta.16иreact-router-dom: 5.1.2

Обновление 2019: для тех, кто работает с react-bootstrap v4 (в настоящее время использует 1.0.0-beta.5) и react-router-dom v4 (4.3.1), просто используйте опору "as" от Nav.Link, здесь полно пример:

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

Алексей
источник
только что попробовал, он просто не работает с 'as = {NavLink}'.
lannyboy 06
1
Это работает на реактивном маршрутизаторе v5 с react-bootstrap 1 и
proc
Я пришел из Vue.js, где boostrap vue просто реализует и управляет параметром «to», и мне это намного проще. В любом случае спасибо за совет, он очень помог!
egdavid 08
1
Используйте это решение вместо LinkContainerfrom, react-router-bootstrapпотому что это решение поддерживает activeClassName.
takasoft 03
Спасибо @Alexey. Потратил часы, пытаясь заставить LinkContainer работать, а потом нашел этот ответ.
Дэвид Исли
31

Вы пробовали использовать response-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
источник
1
Это хорошо работает! Никаких проблем со стилем и намного проще, чем другие ответы, требующие переопределения, вы также можете переопределить с помощью HoC, чтобы избежать повторения href / to.
Тим Линд
1
Это настолько чисто, что я использовал его прямо сейчас с «пустым целевым объектом» для внешней ссылки, и он работает очень хорошо. Спасибо
Сауло Гомес
1
Это лучше, без необходимости включать другой пакет.
sbk201
2
Только что обновился до 1.0.0-beta.5. Кажется, они убрали поддержку componentClass :(
Nate-Bit Int
12

Вы можете избежать использования LinkContainer from response-router-bootstrap. Впрочем, 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>
Алексей Кутало
источник
5

Вот решение для использования с реактивным маршрутизатором 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.transitionTo(href)использованияrouter.history.push(href)
Девасатьям
3

IndexLinkContainer - лучший вариант, чем LinkContainer, если вы хотите, чтобы внутренний элемент NavItem выделял, какой из них активен, на основе текущего выбора. Обработчик ручного выбора не требуется

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? не нашел нигде в документации, хотя ...
Тим Нгуен
@ThomasLe Проверьте, используете ли вы Component vs PureComponent. У меня было несколько обновленных проблем, исправленных переключением на Компонент
FrozenKiwi
2

Вы можете использовать историю , только не забудьте создать компонент с роутером :

в 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>
5ar
источник
0

Чтобы добавить функциональность с помощью свойства «activeKey» в бета-версию response-bootstrap v_1.0, используйте этот формат:

<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>
Молодой скутер
источник