React-Bootstrap ลิงค์ไอเท็มในการนำทาง


86

ฉันมีปัญหาเกี่ยวกับสไตล์การใช้ react-router และ react-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) อยู่ที่นั่นแล้ว

เนื่องจากคำเตือนข้างต้นการตอบสนองจะถูกบังคับให้ปฏิบัติต่อจุดยึดทั้งสองในฐานะพี่น้องซึ่งทำให้เกิดปัญหารูปแบบ


4
ฉันจะต้องจบลงด้วยการใช้linkcontainer
chad schmidt

3
คุณช่วยยกตัวอย่างได้ไหม
Paschalidis Christos

5
ฉันเป็นคนเดียวที่ปัญหาไม่ได้รับการแก้ไขโดยไม่ใช่คำตอบที่ยอมรับ แต่เป็นคำตอบที่สอง
Ejaz Karim

1
@chadschmidt โปรดเปลี่ยนคำตอบที่ยอมรับเป็นstackoverflow.com/a/36933127/1826429
Goldy

249

การใช้LinkContainerจากreact-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>

นี่เป็นข้อควรทราบสำหรับตัวเองในอนาคตเมื่อ googling ปัญหานี้ ฉันหวังว่าคนอื่นอาจได้รับประโยชน์จากคำตอบนี้



4
วิธีการสลับ activeClassName?
Anyul Rivas

หากคุณไม่สามารถทำงานนี้ได้เพียงตรวจสอบให้แน่ใจว่าเส้นทางของคุณรวมอยู่ใน React Router
Anant Simran Singh

8
สิ่งนี้ไม่สามารถใช้สไตล์ "ใช้งานอยู่" กับ NavItems ได้
Daniel Arant

1
ฉันได้เพิ่มคำตอบด้านล่างเพื่อแก้ปัญหาด้วย active / activeKey ไม่ทำงาน ใช้งานได้กับ react-bootstrap v_1.0 beta ด้วย! (หากต้องการใช้กับเวอร์ชันปกติเพียงแค่ย่อย Nav รายการไปมาจาก NavItem และอื่น ๆ )
Young Scooter

54

อัพเดต 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) เพียงใช้ "เป็น" prop จาก 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

2
สิ่งนี้ใช้ได้กับ react router v5 พร้อม react-bootstrap 1 และตอบสนอง 16.8
proc

1
ใช้วิธีนี้แทนLinkContainerจากเพราะการแก้ปัญหานี้สนับสนุนreact-router-bootstrap activeClassName
takasoft

1
หลังจากชั่วโมงของการศึกษาปัญหานี้นี้เป็นทางออกที่ดีที่สุด
Oana Andone

1
นี่เป็นวิธีแก้ปัญหาที่ถูกต้องและควรระบุว่าเป็นคำตอบ
Stephan Bakkelund Valois

31

คุณได้ลองใช้ 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
ใช้งานได้ดี! ไม่มีปัญหาในการจัดแต่งทรงผมและง่ายกว่าคำตอบอื่น ๆ ที่ต้องมีการลบล้างคุณยังสามารถแทนที่ด้วย HoC เพื่อหลีกเลี่ยงการทำซ้ำ href / to
Tim Lind

1
นี่สะอาดมากฉันใช้ตอนนี้กับ "เป้าหมายว่าง" สำหรับลิงก์ภายนอกและทำงานได้ดีมาก ขอบคุณ
Saulo Gomes

1
จะดีกว่าโดยไม่จำเป็นต้องรวมแพ็คเกจอื่น
sbk201

2
เพิ่งอัปเกรดเป็น 1.0.0-beta.5 ดูเหมือนว่าพวกเขาจะลบการรองรับ componentClass :(
Nate-Bit Int

12

คุณสามารถหลีกเลี่ยงการใช้LinkContainerจาก react-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

นี่คือวิธีแก้ปัญหาสำหรับใช้กับ 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
};

แทนที่จะใช้การrouter.transitionTo(href)ใช้งานrouter.history.push(href)
Devasatyam

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

btw แค่อยากรู้ว่าคุณหาได้IndexLinkContainerอย่างไร? ไม่พบที่ใดใน docs tho ...
Thiem Nguyen

@ThomasLe ตรวจสอบโดยใช้ Component vs PureComponent ฉันมีปัญหาที่อัปเดตบางอย่างได้รับการแก้ไขโดยเปลี่ยนไปใช้ Component
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>

0

หากต้องการเพิ่มฟังก์ชันด้วย "activeKey" prop ใน react-bootstrap v_1.0 beta ให้ใช้รูปแบบนี้:

<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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.