Интегрируйте активный маршрутизатор React NavLink с дочерним компонентом

Мое меню сейчас выглядит так:

<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 стороннего компонента.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
5
0
7 020
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете использовать реквизиты 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; }

Я не смогу этого сделать. MenuItem не является компонентом, который я закодировал. Это из библиотеки пользовательского интерфейса под названием blueprintjs.

Krimson 22.04.2018 06:48

вы можете написать собственный css?

Giang Le 22.04.2018 06:52

я редактировал свои ответы. Вы можете сделать это, добавив собственный css .custom-active-class .custom-link-class{ background-color: red; }

Giang Le 22.04.2018 06:56
MenuItem имеет собственный CSS, который добавляется при установке active. Так что да, я мог бы написать собственный CSS, соответствующий внутреннему стилю MenuItem, но это похоже на хакерский способ сделать это. Мне нужен простой способ переключить опору active
Krimson 22.04.2018 07:01

К сожалению, 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}
        />
      )}
    />
  );
};

Это более простой и лаконичный ответ, чем принятый.

John 20.09.2018 19:18

Это нарушает работу подменю, которую поддерживает MenuItem, когда вы можете использовать свойство text. text = { (true)? (<NavLink to = "/applications/home">Applications</NavLink>):(<span>Test<‌​/span>)}

Barkermn01 01.10.2018 14:31

Можете ли вы привести пример того, как это используется, например, как получить activeOnlyWhenExact?

Max Carroll 23.10.2019 11:57

Допустим, у вас есть 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>

Другие вопросы по теме