React Router v6 эквивалент useRouteMatch

При использовании 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.


1
1 578
1

Ответ:

Решено

В 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>
)}

Edit react-router-v6-useroutematch-equivalent

Полный код:

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>
  );
}