Базовое имя, кажется, не принимается во внимание с matchPath в реагирующем маршрутизаторе - PullRequest
11 голосов
/ 25 мая 2019

Я смотрю на ошибку, которую мы имеем в реакции-router-dom версии 5.0.0, и активный класс не применяется к активной ссылке.

Он работает в разработке, когда у нас есть базовое имя / но в нашей среде разработки базовое имя установлено в `/some/basename/'.

Если я назову это matchPath прямо так:

matchPath("/some/basename/business", {
  exact: true,
  location: undefined,
  path: "\/business",
  strict: undefined
})

Затем оно возвращаетnull, если я вызываю matchpath следующим образом, он получает совпадение:

matchPath("/business", {
  exact: true,
  location: undefined,
  path: "\/business",
  strict: undefined
})

Таким образом, похоже, что matchPath не использует basename, потому что после попытки отладки кода я вижу, что matchPathвызывает pathToRegexp, который создает это регулярное выражение:

/^\/business\/?$/i

Кажется, что код использует только свойство path, а не location.pathname.

Я пытался реализовать свой собственный isActive метод регистрации происходящего:

const isActive = (match: Match<any>, historyLocation: Location) =>  {
  const basename = (window.env.REACT_APP_BASE_URI || "/") === "/" ? "" : window.env.REACT_APP_BASE_URI;
  const fullUrl = `${basename.replace(/^(.+?)\/*?$/, "$1")}${historyLocation.pathname}`;

  console.log("----------------------");
  console.log({
    basename,
    fullUrl,
    historyLocation,
    historyLocationPathName: historyLocation.pathname,
    location: window.location.pathname,
    match,
  });
  console.log("----------------------");

  if (!match) {
    return;
  }

  return window.location.pathname.startsWith(`${fullUrl}`);
};

match всегда нулевой в среде, но отлично работает при разработке.

Почему это так?

Ответы [ 2 ]

4 голосов
/ 02 июня 2019

Концепция HTML

Это на самом деле одно из больших преимуществ реактивного маршрутизатора, потому что на этапе разработки вы не знаете, где будет развернут проект.Он может быть развернут в:

  • Первичном домене
  • Субдомене
  • Подкаталоге

Поэтому наилучшим подходом является предоставлениеопределить все относительные URL-адреса в зависимости от базового URL-адреса.basename в React-Router на самом деле не является чем-то новым, и у нас есть тег <base> head в HTML:

<head>
   <base href="https://www.yoursite.com/some/basename/" target="https://www.yoursite.com/other/">
</head>

Этот тег означает, что все относительные URL на странице будут иметь https://www.yoursite.com/some/basename/к ним добавляется, например:

<img src="header.jpg">

Будет то же, что и

<img src="https://www.yoursite.com/some/basename/header.jpg">

, и ко всем относительным ссылкам и действиям с формой будет также присоединено href.


React Router

React-Router в основном использует эту концепцию (однако, не базовый тег), поэтому при установке basename в главном `следующие элементы будут ничего не знать о базовом имени:

  • <Route>
  • <Link>
  • <Redirect>
  • matchPath

поэтому, когда у вас есть такая ссылка:

<Link to="/page2" />

она будет фактически перенаправлена ​​на /some/basename/page2.


basename

  • React-Router Docs предлагает для этого A properly formatted basename should have a leading slash, but no trailing slash. (например, / some / business ).Однако в большинстве современных браузеров это не имеет значения.

matchPath

Теперь поговорим о matchPath.Как я уже говорил, matchPath ничего не знает о базовом имени, поэтому имейте это в виду:

  • убедитесь, что входной URL не имеет базовое имя внутри него.
  • Делайте , а не используйте window.location.pathname, вместо этого используйте реквизиты местоположения React-Router

Тогда все будет в порядке.Так что это всегда будет работать независимо от вашей среды (dev / prod):

matchPath(props.location.pathname, {
    path: '/business',
    exact: true,
});

Примечания

Если все это иметь в виду, вы столкнетесь с какой-то проблемой во всем проекте (включая все ссылки, все перенаправления, все маршруты, а также matchPath), тогда ваше базовое базовое имя задано неверно в производственной среде.

0 голосов
/ 30 мая 2019

На основании этого комментария к выпуску github

basename происходит из HTML-элемента <base href="/foo">, который применяет basename ко всем ссылкам на странице.В этом случае остальная часть HTML не «знает» об этом базовом URL;он просто автоматически добавляется к любому href.

Аналогично, базовое имя в Router - это то, о чем приложение не знает.Он просто <Link>'s к различным маршрутам и не знает о присоединении basename.

Когда вы используете mathPath вместо window.location.pathname, если вы используете location.pathname, предоставленный Router, вы получите путь, соответствующий вашему маршруту, а не весь путь, который включает базовое имя.

matchPath(location.pathname, {
  exact: true,
  location: undefined,
  path: "\/business",
  strict: undefined
})

, и приведенное выше вернет true, если путь равен /some/basename/busines

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...