RegEx, которые соответствуют реакции пути маршрутизатора - PullRequest
1 голос
/ 06 февраля 2020

У меня есть карта маршрутов с маршрутом реагирующего маршрутизатора в качестве ключей, например:

const routes = [
  {
    page: "mySettings",
    label: "pages.mySettings",
    path: "/professionels/mes-reglages.html",
    exact: true
  },
  {
    page: "viewUser",
    label: "pages.viewUser",
    path: "/users/:id/view.html",
    exact: true
  }
];

Я хочу, чтобы из местоположения, полученного с помощью useHistory().location.pathname, совпадал весь путь, соответствующий ключу в реагирующем условия маршрутизатора, например:

  • (pathname) => get(routesMap, "/professionels/mes-reglages.html") => должны совпадать routesMap.get('/professionels/mes-reglages.html')
  • (pathname) => get(routesMap, "/users/11/view.html") => должны совпадать routesMap.get('/users/:id/view.html')

и все пути реакции-маршрутизатора, поэтому это тоже должно работать:

  • (pathname) => get(routesMap, "/users/11/settings/10/items/24/view.html") => должно соответствовать routesMap.get('/users/:userId/settings/:settingId/items/:id/view.html')

Я начал здесь, любая идея, как я могу это сделать что с регулярным выражением?

https://codesandbox.io/s/youthful-wing-fjgm1

1 Ответ

1 голос
/ 19 февраля 2020

Основываясь на ваших комментариях, я немного изменил код и написал функцию рэпера для вашего поиска. Следующие правила, которые вы должны соблюдать при создании URL:

  • Последний идентификатор всегда заменяется на {id}
  • Все остальные идентификаторы заменяются частью URL на идентификатор без множественное число и присоединенный "Id" ("/ users / 111" -> "/ users / {userId}")

Это будет функция:

const getRouteFromPath = (map, url) => {
  if (url.match(/\/\d+\//g).length > 1) {
    let allowedUrlPart = getAllowedIdQualifier(map);
    let urlParts = url.match(/(?<=\/)\w+(?=\/\d+\/)/g);
    urlParts.forEach(val => {
      if (!allowedUrlPart.includes(val)) {
        urlParts = urlParts.slice(urlParts.indexOf(val), 1);
      }
    });
    urlParts.forEach((val, key, arr) => {
      if (key === arr.length - 1) {
        let regex = new RegExp("(?<=/" + val + "/)\\d+", "g");
        let replacement = ":id";
        url = url.replace(regex, replacement);
      } else {
        let regex = new RegExp("(?<=/" + val + "/)\\d+", "g");
        let replacement = ":" + val.slice(0, -1) + "Id";
        url = url.replace(regex, replacement);
      }
    });
    return map.get(url);
  } else {
    url = url.replace(/\/\d+\//g, "/:id/");
    return map.get(url);
  }
};

const getAllowedIdQualifier = map => {
  let allowedQualifiers = [];
  map.forEach(val => {
    let allowed = val.path.match(/(?<=\/)\w+(?=\/:)/g);
    allowed.forEach(e => {
      if (!allowedQualifiers.includes(e)) {
        allowedQualifiers.push(e);
      }
    });
  });
  return allowedQualifiers;
};

export default getRouteFromPath;

как параметр Вы передаете в качестве первого параметра url для сопоставления, а в качестве второго параметра - карту маршрутов и вызываете функцию getRoute () вместо прямой map.get (), вызывающей вас при использовании ранее.

Вот Пример с URL, настроенными в соответствии с правилами, так как вам нужны некоторые правила, чтобы иметь возможность применять RegEx.

РЕДАКТИРОВАТЬ:

Я настроил сценарий так, чтобы он сначала читал карту и определял разрешенные пути, которые принимают идентификатор, а затем проверяет возможные идентификаторы из фактического URL против него.

https://codesandbox.io/s/kind-moon-9oyj9?fontsize=14&hidenavigation=1&theme=dark

...