При использовании React Router v5 можно было получить путь (шаблон) для этого маршрута с помощью useRouteMatch
.
const { path } = useRouteMatch();
React Router v6 предлагает аналогичный хук, useMatch
; однако это предполагает получение шаблона, с которым вы хотите сопоставить.
Я бы использовал хук React Router v5 для создания маршрутов, комбинируя текущий путь с известными параметрами.
Например, если я нахожусь на странице продукта приложения для электронной коммерции (допустим, /en/product/:id
) и там есть ссылки на сопутствующие товары (/en/product/1
, /en/product/2
... и т. д.), раньше я мог бы сделать следующее:
const MyComponent = () => {
const { path } = useRouteMatch();
return (
<div>
<Link to = {generatePath(path, { id: 1 })}>Related Product 1</Link>
<Link to = {generatePath(path, { id: 2 })}>Related Product 2</Link>
</div>
);
};
Поскольку /en/product
исходит из API и нигде в коде не объявлено, я бы хотел, чтобы URL-адреса обновлялись на основе текущего пути. Если пользователь находится на /es/producto
, то ссылки будут автоматически обновлены до /es/producto/1
.
Я видел решения на SO, где было предложено использовать matchRoutes
, однако это кажется крайне неэффективным, особенно потому, что маршруты динамически генерируются из внешнего API.
const useCurrentPath = () => {
const location = useLocation()
const [{ route }] = matchRoutes(routes, location)
return route.path
}
Я создал небольшую демонстрацию, чтобы проиллюстрировать, как это работало:
Демонстрация тестовой среды кода
🤔 А знаете ли вы, что...
JavaScript обеспечивает обработку ошибок с использованием конструкции try...catch.
В react-router-dom@6
нет замены крючку v5 useRouteMatch
. Ссылки и маршруты больше не должны быть связаны с шаблоном path
, поскольку они могут просто использовать относительные маршруты и ссылки. Вместо того, чтобы пытаться получить доступ к шаблону пути маршрута, он может просто перемещаться относительно текущего пути.
Пример:
Это перемещает от "/route-a/2"
к "/route-a/2/../1"
или, скорее, "/route-a/1"
.
const { pathname } = useLocation();
const { id } = useParams();
// if there is a current subroute id && a related sibling id to navigate to
{id && RELATED_ID && (
<Link to = {`${pathname}/../${RELATED_ID}`}>
Go to Nested Route {RELATED_ID}
</Link>
)}
Полный код:
import {
BrowserRouter,
Link,
Route,
Routes,
useParams,
useLocation
} from "react-router-dom";
import "./styles.css";
const RELATED_ID = 1;
const MyComponent = ({ title }) => {
const { pathname } = useLocation();
const { id } = useParams();
return (
<div>
<h1>
{title} {id}
</h1>
<pre>{pathname}</pre>
{id && RELATED_ID && (
<Link to = {`${pathname}/../${RELATED_ID}`}>
Go to Nested Route {RELATED_ID}
</Link>
)}
</div>
);
};
export default function App() {
return (
<div className = "app">
<BrowserRouter>
<nav>
<Link to = "/">Home</Link>
<Link to = "/route-a">Route A</Link>
<Link to = "/route-b">Route B</Link>
<Link to = "/route-a/1">Nested Route A1</Link>
<Link to = "/route-a/2">Nested Route A2</Link>
<Link to = "/route-b/1">Nested Route B1</Link>
<Link to = "/route-b/2">Nested Route B2</Link>
</nav>
<Routes>
<Route
path = "/route-b"
element = {<MyComponent title = "Nested Route" />}
/>
<Route
path = "/route-a"
element = {<MyComponent title = "Nested Route" />}
/>
<Route
path = "/route-b/:id"
element = {<MyComponent title = "Nested Route" />}
/>
<Route
path = "/route-a/:id"
element = {<MyComponent title = "Nested Route" />}
/>
<Route path = "/" />
</Routes>
</BrowserRouter>
</div>
);
}