Мое меню сейчас выглядит так:
<Menu>
<MenuItem text = "link1" />
<MenuItem text = "link2" />
</Menu>
Для интеграции с react-router-dom я модифицировал следующим образом:
<Menu>
<NavLink to = "link1">
<MenuItem text = "link1" />
</NavLink>
<NavLink to = "link2">
<MenuItem text = "link2" />
</NavLink>
</Menu>
Мой компонент MenuItem поддерживает стилизацию текущей "активной" ссылки следующим образом:
<MenuItem active text = "link1" />
Как мне интегрировать "активный" стиль маршрута с react-router-dom?
Есть ли какое-то логическое значение, которое я могу установить следующим образом?
<MenuItem active = {isRouteActive} text = "link1" />
Редактировать:MenuItem - компонент от Blueprintjs. Когда параметр active установлен, возможно, к компоненту применяются некоторые внутренние правила стилизации. Я мог бы использовать опору activeClassName на NavLink, но я не хочу копировать CSS стороннего компонента.





Вы можете использовать реквизиты activeClassName от реактивного маршрутизатора.
<NavLink activeClassName = "custom-active-class" to = "link1">
<MenuItem className = "custom-link-class" text = "link1" />
</NavLink>
<NavLink activeClassName = "custom-active-class" to = "link2">
<MenuItem className = "custom-link-class" text = "link2" />
</NavLink>
и немного измените свой css
.custom-active-class .custom-link-class{
background-color: red;
}
вы можете написать собственный css?
я редактировал свои ответы. Вы можете сделать это, добавив собственный css .custom-active-class .custom-link-class{ background-color: red; }
MenuItem имеет собственный CSS, который добавляется при установке active. Так что да, я мог бы написать собственный CSS, соответствующий внутреннему стилю MenuItem, но это похоже на хакерский способ сделать это. Мне нужен простой способ переключить опору activeК сожалению, NavLink от rr4 пока не предлагает способ передать информацию isActive своим потомкам (MenuItem).
Хорошо, что rr4 использует подход, ориентированный на компоненты, так что буквально все является просто реагирующим компонентом, NavLink сам по себе является пользовательским компонентом, состоящим из:
<Route/> (обрабатывает сопоставление маршрутов)<Link/> (отправляет действие маршрута)Мы можем создать нашу версию пользовательской сортировки ссылок, например:
const NavLink = ({
to,
children,
className,
activeClassName,
...rest
}) => {
const path = typeof to === "object" ? to.pathname : to;
return (
<Route
path = {path}
children = {({ match }) => {
const isActive = !!match;
return (
<Link
{...rest}
className = {
isActive
? [className, activeClassName].filter(i => i).join(" ")
: className
}
to = {to}
>
{typeof children === 'function' ? children(isActive) : children}
</Link>
);
}}
/>
);
};
export default NavLink;
а затем используйте его как:
<Menu>
<NavLink to = "link1">
{isActive => <MenuItem active = {isActive} text = "link1" />}
</NavLink>
<NavLink to = "link2">
{isActive => <MenuItem active = {isActive} text = "link2" />}
</NavLink>
</Menu>
Это использует рендеринг реквизита для передачи состояния isActive от родителя к потомку. Это должно работать нормально, но чтобы полностью имитировать способ (например, поддержку доступности) NavLink работает в rr4, может все еще потребоваться исправление на основе его выполнение.
В этом конкретном случае использовать локальное состояние со ссылкой может быть проще
state = { activeLink: '' }
render() {
return (
<Menu>
<Link to='link1' onClick = {() => this.setState({ activeLink: 'link1' })>
<MenuItem active = {this.state.activeLink === 'link1'} text='link1' />
</Link>
<Link to='link2' onClick = {() => this.setState({ activeLink: 'link2' })>
<MenuItem active = {this.state.activeLink === 'link2'} text='link2' />
</Link>
</Menu>
)
}
В итоге я понял это. Я создал свой собственный компонент, используя состав компонента Route
const MenuItemExt = ({ icon, text, to, activeOnlyWhenExact }) => {
return (
<Route
path = {to}
exact = {activeOnlyWhenExact}
children = {({match, history}) => (
<MenuItem
active = {match}
icon = {icon}
onClick = {() => {
history.push(to);
}}
text = {text}
/>
)}
/>
);
};
Это более простой и лаконичный ответ, чем принятый.
Это нарушает работу подменю, которую поддерживает MenuItem, когда вы можете использовать свойство text. text = { (true)? (<NavLink to = "/applications/home">Applications</NavLink>):(<span>Test</span>)}
Можете ли вы привести пример того, как это используется, например, как получить activeOnlyWhenExact?
Допустим, у вас есть 2 маршрута:
/ admin
/ admin / привилегии
Вы хотите, чтобы текст панели навигации «Admin» был активным, когда открыта любая из указанных выше ссылок. Вы можете добиться этого примерно так:
<NavLink
exact
to = "/admin"
className = "..."
activeClassName = "..."
isActive = {(match, location) => {
let pathStrings = location.pathname.split('/');
// pathstrings will be ['/', 'admin', '/', 'privileges']
// should you add a new subroute, say /admin/locations/ the code would still work
if (match) {
return true;
} else if (pathStrings[1] === 'admin') {
return true;
} else {
return false;
}
}}
>
Admin
</NavLink>
Я не смогу этого сделать.
MenuItemне является компонентом, который я закодировал. Это из библиотеки пользовательского интерфейса под названием blueprintjs.