我使用 react-router-bootstrap (https://www.npmjs.com/package/react-router-bootstrap)组件时遇到活动链接问题。当我导航到关于时,活动类不仅会出现在关于上,还会出现在主页中。
Active Link react-router's issue
来自 react-bootstrap (https://react-bootstrap.github.io/)的导航组件:
NavLinks.jsx
import React, { Component } from 'react';
import { Nav, NavItem } from 'react-bootstrap';
import HashNavItem from '../../Navigation/HashNavItem';
// import Flags from './Flags/Flags'
import "./NavLinks.css";
const routes = [{
name: 'Home',
path: '/',
external: false
},{
name: 'About',
path: '/about',
external: false
}, {
name: 'Stores',
path: '/#stores',
external: false
}, {
name: 'My Account',
path: 'http://my-react.appicar.com/',
external: true
}, {
name: 'Services',
path: '/#services',
external: false
}, {
name: 'Reviews',
path: '/#reviews',
external: false
}, {
name: 'Contact',
path: '/#contact',
external: false
}];
export default class MainNav extends Component {
handleClick(e) {
e.preventDefault();
alert('hola');
}
render() {
let template;
return (
<Nav>
{
routes.map((route, key) => {
if (route.external) {
template = (
<NavItem eventKey={ 'nav-' + key } href={ route.path } key={ key }>
{route.name}
</NavItem>
);
} else {
template = <HashNavItem eventKey={ 'nav-' + key } name={ route.name } to={ route.path } key={ key } />;
}
return template;
})
}
</Nav>
);
}
}
HashNavItem.jsx
import React, { Component } from "react";
import { NavItem } from 'react-bootstrap';
import { LinkContainer } from "react-router-bootstrap";
export default class HashNavItem extends Component {
constructor(props) {
super(props);
// Atributes.
this.hashFragment = '';
this.observer = null;
this.asyncTimerId = null;
this.scrollFunction = null;
// States.
this.state = {
key: props.eventKey,
name: props.name,
to: props.to
}
// Methods.
this.reset = this.reset.bind(this);
this.getElAndScroll = this.getElAndScroll.bind(this);
this.hashLinkScroll = this.hashLinkScroll.bind(this);
this.handleClick = this.handleClick.bind(this);
}
reset() {
this.hashFragment = '';
if (this.observer !== null) this.observer.disconnect();
if (this.asyncTimerId !== null) {
window.clearTimeout(this.asyncTimerId);
this.asyncTimerId = null;
}
}
getElAndScroll() {
const element = document.getElementById(this.hashFragment);
if (element !== null) {
this.scrollFunction(element);
this.reset();
return true;
}
return false;
}
hashLinkScroll() {
// Push onto callback queue so it runs after the DOM is updated
window.setTimeout(() => {
if (this.getElAndScroll() === false) {
if (this.observer === null) {
this.observer = new MutationObserver(this.getElAndScroll);
}
this.observer.observe(document, {
attributes: true,
childList: true,
subtree: true,
});
// if the element doesn't show up in 10 seconds, stop checking
this.asyncTimerId = window.setTimeout(() => {
this.reset();
}, 10000);
}
}, 0);
}
handleClick(e) {
this.reset();
if (this.props.onClick) this.props.onClick(e);
if (typeof this.props.to === 'string') {
this.hashFragment = this.props.to
.split('#')
.slice(1)
.join('#');
} else if (
typeof this.props.to === 'object' &&
typeof this.props.to.hash === 'string'
) {
this.hashFragment = this.props.to.hash.replace('#', '');
}
if (this.hashFragment !== '') {
this.scrollFunction =
this.props.scroll || (el =>
el.scrollIntoView(this.props.smooth ? { behavior: 'smooth' } : undefined)
);
this.hashLinkScroll();
}
}
render() {
return (
<LinkContainer to={ this.state.to }>
<NavItem eventKey={ this.state.key } key={ this.state.key } onClick={ this.handleClick }>{ this.state.name } </NavItem>
</LinkContainer>
);
}
}
App.jsx
import React, { Component } from "react";
import { Router, Switch, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import MainNav from './MainNav/MainNav';
import Logo from './Logo/Logo';
import Footer from './Footer/Footer';
import Copyright from './Copyright/Copyright';
import HomePage from './HomePage/HomePage';
import AboutPage from './AboutPage/AboutPage';
import Error404 from './Error404/Error404';
import './App.css';
class App extends Component {
render() {
return (
<Router history={ createBrowserHistory() }>
<div>
<MainNav />
<Logo />
<Switch>
<Route exact path="/" component={ HomePage } />
<Route exact path="/about" component={ AboutPage } />
<Route exact path="/404" component={ Error404 } />
</Switch>
<Footer />
<Copyright />
</div>
</Router>
);
}
}
export default App;
有谁知道为什么 主页 始终标记为有效?
答案 0 :(得分:1)
由于您已经使用了react-bootstrap
软件包,因此可以像这样解决您的问题:
import { NavLink } from "react-router-dom";
import { Nav } from "react-bootstrap";
<Nav>
<Nav.Link as={NavLink} exact to="/">
Home
</Nav.Link>
<Nav.Link as={NavLink} exact to="/about">
About
</Nav.Link>
</Nav>
这里的关键是将exact
属性与Nav.Link
组件一起使用,并将as
属性设置为NavLink
,如上面的代码片段所示。
Check the documentation of the NavLink
's exact
property了解更多信息。
答案 1 :(得分:0)
我认为它与你的路线有关(所以react-router不一定是react-router-bootstrap)。我看到你在路线声明中加上'确切'但我会尝试在你的声明中添加'严格'。在我正在开发的应用程序中,我必须这样做才能使我的高阶组件验证包装器正常工作。
如果这不起作用那么我的猜测就是你如何迭代routes数组来动态创建nav-links。可能存在一个问题,即通过构建导航链接的方式清除活动状态。对不起,我没有更具体的答案!我还没有获得50+的声誉才能发表评论,所以希望有用的答案必须要做。
答案 2 :(得分:0)
您应该使用 IndexLinkContainer 而不是 LinkContainer