React-Router v6: Pfadmuster für aktuelle Route abrufen

Lesezeit: 5 Minuten

caseyjhols Benutzeravatar
caseyjhol

Ist es möglich, das Pfadmuster für die aktuell passende Route zu erhalten? Beispiel:

<Route
    path=":state/:city*"
    element={
        <Page />
    }
/>
// Page.jsx

function Page() {
    ...
    // usePathPattern doesn't actually exist
    const pathPattern = usePathPattern(); // pathPattern = ":state/:city*"
    ...
}

Ich weiß, dass ich es gebrauchen kann useMatch um zu überprüfen, ob die aktuelle Position mit einem bestimmten Pfadmuster übereinstimmt, aber dann muss die Komponente wissen, was das Pfadmuster ist.

Benutzeravatar von Futian Shen
Futian Shen

Ich habe einen benutzerdefinierten Haken gemacht useCurrentPath mit React-Router v6, um den aktuellen Routenpfad zu erhalten, und es funktioniert für mich

Wenn der aktuelle Pfadname lautet /members/5566 Ich werde Pfad bekommen /members/:id

import { matchRoutes, useLocation } from "react-router-dom"

const routes = [{ path: "/members/:id" }]

const useCurrentPath = () => {
  const location = useLocation()
  const [{ route }] = matchRoutes(routes, location)

  return route.path
}

function MemberPage() {
  const currentPath = useCurrentPath() // `/members/5566` -> `/members/:id`
   
  return <></>
}

Bezug

https://reactrouter.com/en/v6.3.0/api#matchroutes

  • Das hat bei mir super funktioniert. Der benutzerdefinierte Haken ist eine persönliche Präferenz. Jedoch, useLocation + matchRoutes ist die Antwort.

    – Hermann J. Radtke III

    1. Mai um 19:33 Uhr

  • Dies scheint bei verschachtelten Routen mit relativen Pfaden nicht zu funktionieren. Wann zum Beispiel location.pathname ist "/users/123/profile" aber routes[0].path ist "profile" weil es unter verschachtelt ist "users/:id". Hast du dafür eine Lösung?

    – eliw00d

    28. Juli um 20:56 Uhr


Benutzeravatar von m.wrona
m.wrona

Ich bin mir nicht sicher, ob es Ihren Anwendungsfall vollständig löst, aber in meinem Fall habe ich eine Kombination aus verwendet useLocation und useParams. Hier ist der Code:

import React from 'react';
import { useLocation, useParams } from 'react-router-dom';
import type { Location, Params } from 'react-router-dom';

/**
 * Function converts path like /user/123 to /user/:id
 */
const getRoutePath = (location: Location, params: Params): string => {
  const { pathname } = location;

  if (!Object.keys(params).length) {
    return pathname; // we don't need to replace anything
  }

  let path = pathname;
  Object.entries(params).forEach(([paramName, paramValue]) => {
    if (paramValue) {
      path = path.replace(paramValue, `:${paramName}`);
    }
  });
  return path;
};

export const Foo = (): JSX.Element => {
  const location = useLocation();
  const params = useParams();
  const path = getRoutePath(location, params);

  (...)
};

  • Diese Lösung würde brechen, wenn Teile des Pfades denselben Wert haben, z /user/1/badge/1/comment/1. Obwohl dies ein ungewöhnliches Szenario ist, ist diese Lösung immer noch nicht universell zuverlässig.

    – Ben Barkay

    30. April um 12:47 Uhr


  • Besser zu verwenden Reactrouter.com/docs/en/v6/api#matchroutes stattdessen.

    – Hermann J. Radtke III

    1. Mai um 19:32 Uhr

  • @HermanJ.RadtkeIII Link scheint defekt zu sein. Vielleicht meinst du Dies

    – Reimirno

    7. Juli um 3:51

Aus dem Kontext von a Route du kannst die bekommen path über mehrere Methoden, die in dargelegt sind die Dokumente.

Mein Problem war insofern etwas anders, als ich das brauchte path außerhalb des Kontextes der Route und kam zu der folgenden Lösung, die auch für Sie funktionieren sollte:

import {
    matchPath,
    useLocation
} from "react-router-dom";

const routes = [ ':state/:city', ...otherRoutes ];

function usePathPattern() {

    const { pathname } = useLocation();

    return matchPath( pathname, routes )?.path;
}

  • Ihr Dokumentationslink verweist auf die v5-Dokumente, nicht auf die v6-Dokumente, und ist daher nicht hilfreich.

    – Chris Kitching

    16. Januar um 4:25

  • Dokumentation v6: Reactrouter.com/docs/en/v6/utils/match-path

    – aderchox

    15. Juni um 7:08 Uhr

das funktioniert bei mir problemlos

Importieren Sie zuerst uselocation von React-Router-Dom

import { useLocation } from "react-router-dom"

dann

const location = useLocation();
console.log(location.pathname);

Benutzeravatar von RichN
RichN

Dies scheint mit dem zu funktionieren, was sie tatsächlich ab 6.2.1 exportieren, verwendet jedoch eine Komponente, die sie als UNSAFE_ exportieren.

import { UNSAFE_RouteContext } from 'react-router-dom';

const reconstructPath = (matches) =>
  matches
    .map(({ route: { path } }) =>
      path.endsWith('/*') ? path.slice(0, -1) : path ? path + "https://stackoverflow.com/" : ''
    )
    .join('');

const findLastNode = (node) =>
  node.outlet ? findLastNode(node.outlet.props.value) : node;

const usePathPattern = () =>
  reconstructPath(
    findLastNode(React.useContext(UNSAFE_RouteContext)).matches
  );

Tobis Benutzer-Avatar
Tobi

Ich habe zu diesem Zweck einen benutzerdefinierten Hook geschrieben, da OOB derzeit nicht unterstützt zu werden scheint:

Hinweis: Es ist noch nicht gründlich getestet. Also mit Vorsicht verwenden.

import { useLocation, useParams } from 'react-router';

export function useRoutePathPattern() {
  const routeParams = useParams();
  const location = useLocation();

  let routePathPattern = location.pathname;

  Object.keys(routeParams)
    .filter((paramKey) => paramKey !== '*')
    .forEach((paramKey) => {
      const paramValue = routeParams[paramKey];
      const regexMiddle = new RegExp(`\/${paramValue}\/`, 'g');
      const regexEnd = new RegExp(`\/${paramValue}$`, 'g');

      routePathPattern = routePathPattern.replaceAll(
        regexMiddle,
        `/:${paramKey}/`,
      );
      routePathPattern = routePathPattern.replaceAll(regexEnd, `/:${paramKey}`);
    });

  return routePathPattern;
}

Benutzeravatar von Labithiotis
Labithiotis

Um die passende Route in React-Router v6 zu finden, müssen Sie die verwenden matchPath Funktion. Sie müssen alle Ihre Routen in einer Variablen wie einem Array speichern. Dann können Sie alle Routen durchlaufen und diese Funktion verwenden, um die passende Route zu finden. Da es mit dem ersten Wahrheitswert übereinstimmt, müssen Sie sie idealerweise in derselben Reihenfolge durchlaufen, in der Sie sie gerendert haben.

Dies ist keine perfekte Lösung, da verschachtelte Routen möglicherweise nicht verarbeitet werden, es sei denn, Sie speichern diese in derselben Variablen.

Hier ist ein Beispiel:

routen.ts

const routes = [
  { name: 'Home', path: '/home', element: Home },
  { name: 'Profile', path: '/profile', element: Profile },
  { name: '404', path: '*', element: NotFound },
];

App.tsx

<App>
  <BrowserRouter>
    <Header />
    <Routes>
      {routes.map((route, key) => (
        <Route key={key} path={route.path} element={<route.element />} />
      ))}
    </Routes>
  </BrowserRouter>
</App

useMatchedRoute.tsx

import { matchPath } from 'react-router';

export function useMatchedRoute() {
  const { pathname } = useLocation();
  for (const route of routes) {
    if (matchPath({ path: route.path }, pathname)) {
      return route;
    }
  }
}

Header.tsx

export function Header() {
  const route = useMatchedRoute();

  return <div>{route.name}</div>
}

1434340cookie-checkReact-Router v6: Pfadmuster für aktuelle Route abrufen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy