Mongez React Router, лучшая система маршрутизации, которую вы когда-либо будете использовать с React


Содержание
  1. Введение
  2. Выделенные особенности
  3. Перед продолжением
  4. Установка
  5. Использование
  6. Ленивая загрузка приложений
  7. Создание приложений
  8. Псевдоним пути приложений
  9. Декларация модулей приложений
  10. Структура модулей
  11. Концепция входа в модуль
  12. Определение списка приложений
  13. Определение маршрутов модулей
  14. Промежуточное программное обеспечение маршрута
  15. Группированные маршруты
  16. Базовый макет страницы
  17. Расширение базового макета
  18. Относительность маршрутов
  19. Структура пути маршрута
  20. Конфигурации маршрутизаторов
  21. Корневой компонент
  22. Навигация по ссылкам
  23. Компонент перенаправления
  24. Структура маршрутов
  25. Получение параметров маршрутизатора
  26. Дикая карта маршрута
  27. Более ограниченные сегменты маршрута
  28. Переключение на другой код локали
  29. Переход к маршруту
  30. Переход назад
  31. Обновление страницы
  32. Получение маршрута текущей страницы
  33. Получение полного url страницы
  34. Конкатенация маршрутов
  35. Обновление строки запроса
  36. Получение текущего хэш-значения в url
  37. Получение строки запроса
  38. Получение базового url проекта
  39. Получить текущее направление страницы
  40. Direction Is
  41. Получить предыдущий маршрут
  42. События маршрутизатора
  43. Заключение

Введение

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

Представьте, что у вас есть проект, который содержит панель администратора и фронт-офис сайта, Mongez React Router (MRR) позволит нескольким командам/членам работать отдельно в каждом приложении, и оба приложения будут находиться в одном проекте без каких-либо конфликтов, кроме того, вы можете совместно использовать общие стили/активы.

Выделенные особенности

  • ✅ Объявление маршрутов более читабельным и чистым способом.
  • ✅ Общие базовые макеты для нескольких маршрутов, что позволяет избежать повторного рендеринга для таких частей, как верхний и нижний колонтитулы.
  • ✅ Простые определения Middleware
  • ✅ Ленивая загрузка для целых приложений и модулей для уменьшения размера производственного пакета.
  • ✅ Группировка маршрутов с общими функциями, такими как установка базового пути, общее промежуточное ПО между маршрутами.
  • ✅ Переключение языков без перезагрузки страницы.
  • ✅ Опциональное обновление той же страницы при повторном переходе на нее.
  • ✅ Множество помощников для перехода между маршрутами с помощью функций.
  • ✅ Работа с функциями для навигации вместо хуков.
  • ✅ Возможность перенаправления на маршрут «Страница не найдена» или просто отрисовка компонента.
  • ✅ Определяет прелоадер (например, Progress Bar), пока не загрузится пакет приложений/модулей.
  • ❌ Отсутствие некрасивой записи маршрутов в компонентах.

Перед продолжением

Эта документация проиллюстрирует возможности пакета, однако рекомендуется использовать его вместе с Mongez React для лучшей организации проекта.

Под капотом используется React Router DOM.

Установка

yarn add @mongez/react-router

Или

npm i @mongez/react-router

Использование

В вашем файле src/index импортируйте пакет и очистите секцию ReactDOM.render.

// src/index.ts
import router from "@mongez/react-router";

// remove the following code from the file
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь давайте добавим маршрут для нашей главной страницы

// src/index.ts
import router from "@mongez/react-router";
import HomePage from "./Home";

router.add("/", HomePage);

// Start scanning for all of registered routes
router.scan();
Вход в полноэкранный режим Выход из полноэкранного режима

Мы импортировали наш компонент HomePage, который является обычным компонентом react, затем мы использовали метод router.add для определения нашего первого маршрута, который определяет маршрут нашей домашней страницы.

Затем мы вызвали router.scan(), чтобы начать сканирование всех зарегистрированных маршрутов в маршрутизаторе для вызова нужного маршрута.

Пожалуйста, не забудьте установить router.scan после объявления всех ваших маршрутов.

Ленивая загрузка приложений

Одна из самых полезных функций в этом инструменте — ленивая загрузка приложений, особенно если у вас несколько приложений в одном проекте, поэтому давайте посмотрим, как это можно сделать.

Например, ни один из файлов admin не будет загружен, пока пользователь не перейдет к маршруту /admin в браузере, а также любой модуль внутри администратора, например, модуль administrators.

Создание приложений

Любой проект react может содержать одно или несколько приложений в одном проекте, например, front-office для основного сайта и admin dashboard для управления сайтом.

Итак, давайте создадим эти два приложения в директории src/apps, чтобы все выглядело следующим образом:

|--- src
  |--- apps
     |-- front-office
     |-- admin
  |--- index.ts
Вход в полноэкранный режим Выход из полноэкранного режима

Псевдоним пути приложений

Чтобы заставить работать приложения с ленивой загрузкой, нам нужно определить абсолютный путь для наших приложений, используя файл tsconfig.json или используя link-module-alias, что более рекомендуется.

Если вы используете link-module-alias, откройте файл package.json и добавьте в него следующий код:

"scripts": {
  "postinstall": "link-module-alias"
},
"_moduleAliases": {
  "apps": "src/apps"
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Затем запустите yarn postinstall или npm run postinstall.

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

Декларация модулей приложений

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

  1. front-office-modules.json для определения структуры приложения, модулей и его внутренних маршрутов.
  2. Файл front-office-provider.ts в качестве точки входа в приложение, так как он будет вызываться в самом начале перед вызовом любого внутреннего модуля внутри приложения.

Имя файла modules.json должно быть в такой последовательности appName-modules.json, как мы назвали наш файл модулей администратора.
Провайдер приложения должен быть назван appName-provider.ts или appName-provider.js, если вы используете Javascript.

|--- src
  |--- apps
     |-- front-office
        |-- front-office-modules.json
        |-- front-office-provider.ts
     |-- admin
  |--- index.ts
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь откройте файл front-office-modules.json и поместите в него следующий код.

{
  "name": "front-office",
  "path": "/",
  "modules": [
    {
      "entry": ["/"],
      "module": "home"
    }
  ]
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Давайте подробно рассмотрим каждый ключ в этом файле.

Структура модулей

Каждое приложение состоит из списка модулей, каждый модуль должен иметь как минимум файл provider.

Файл provider.ts|.js будет вызван непосредственно, когда браузер перейдет по пути входа в модуль, что будет показано позже. В этом файле должны быть импортированы настройки нашего модуля, например, его маршруты.

Концепция входа в модуль

Давайте рассмотрим пример для наглядности.

Допустим, мы работаем над проектом интернет-магазина, который будет содержать панель счетов клиентов, эта панель может иметь следующие маршруты:

  • /account/dashboard
  • /account/edit-profile
  • /account/order-history
  • /account/order-history/:id

Все предыдущие маршруты являются частью модуля account в нашем проекте, также все они начинаются с сегмента /account.

В этом случае структура нашего проекта будет выглядеть следующим образом:


|--- src
  |--- apps
      |-- front-office
        |-- account
          |-- components
            |-- DashboardPage.tsx
            |-- EditProfilePage.tsx
            |-- OrderHistoryList.tsx
            |-- SingleOrderHistory.tsx
        |-- front-office-modules.json
        |-- front-office-provider.ts
      |-- admin
  |--- index.ts
Вход в полноэкранный режим Выход из полноэкранного режима

В этом смысле, все они имеют один модуль account и все они начинаются с /account, чтобы объявить это в нашем front-office-modules.json мы добавим только начальный сегмент всех этих маршрутов /account.

В результате Mongez React Router загрузит модуль account, когда увидит, что маршрут начинается с /account.

{
  "name": "front-office",
  "path": "/",
  "modules": [
    {
      "entry": ["/account"],
      "module": "account"
    },
    {
      "entry": ["/"],
      "module": "home"
    }
  ]
}
Вход в полноэкранный режим Выход из полноэкранного режима

Еще одна вещь, о которой следует упомянуть, заключается в том, что мы также можем загрузить модуль с различными маршрутами, например, если /login является частью нашего модуля account, то мы можем добавить его в раздел entry.

{
  "name": "front-office",
  "path": "/",
  "modules": [
    {
      "entry": ["/account", "/login"],
      "module": "account"
    },
    {
      "entry": ["/"],
      "module": "home"
    }
  ]
}
Вход в полноэкранный режим Выход из полноэкранного режима

Ключ entry принимает только первый сегмент маршрута, поэтому не определяйте внутри него весь маршрут.

{
  "name": "front-office",
  "path": "/",
  "modules": [
    {
      "entry": ["/account", "/login"],
      "module": "account"
    },
    {
      "entry": ["/"],
      "module": "home"
    }
  ]
}
Вход в полноэкранный режим Выход из полноэкранного режима

{
  "name": "front-office",
  "path": "/",
  "modules": [
    {
      "entry": ["/account/dashboard", "/account/edit-profile", "/login"],
      "module": "account"
    },
    {
      "entry": ["/"],
      "module": "home"
    }
  ]
}
Войти в полноэкранный режим Выход из полноэкранного режима

Определение списка приложений

Теперь давайте создадим файл src/shared/apps-list.ts, чтобы задать список приложений.

Для лучшей организации мы создадим каталог shared внутри нашего src, чтобы мы могли задать общие конфигурации для нескольких приложений.

|--- src
  |--- apps
     |-- front-office
        |-- front-office-modules.json
        |-- front-office-provider.ts
     |-- admin
  |--- shared
     |-- apps-list.ts
  |--- index.ts
Вход в полноэкранный режим Выход из полноэкранного режима
// src/shared/apps-list.ts

import { setApps } from "@mongez/react-router";

import frontOfficeApp from "apps/front-office/front-office-modules.json";

setApps([frontOfficeApp]);
Войдите в полноэкранный режим Выход из полноэкранного режима

Мы использовали псевдоним apps/ напрямую, так как уже использовали псевдоним path.

Теперь давайте вернемся к нашему индексному файлу и импортируем наш файл apps-list.ts.

// src/index.ts
import "./shared/apps-list";

import router from "@mongez/react-router";

router.scan();
Вход в полноэкранный режим Выход из полноэкранного режима

С этого момента вы можете лениво загружать любое новое приложение или любой новый модуль, создав его каталог и провайдера.

Определение маршрутов модулей

Теперь мы импортировали наш список приложений, и все работает хорошо, за исключением того, что ни один маршрут не будет загружен!

Причина этого в том, что мы не объявили никаких маршрутов, поскольку мы только сообщили MRR для загрузки провайдера модуля, поэтому теперь нам нужно определить наши маршруты для нашего модуля.

В src/apps/front-office/home у нас должно быть два файла: provider.ts и routes.ts.

// src/apps/front-office/home/provider.ts

import "./routes";
Вход в полноэкранный режим Выход из полноэкранного режима

Мы только что импортировали наш файл routes.ts, теперь давайте добавим туда наши маршруты.

// src/apps/front-office/home/routes.ts

import router from "@mongez/router";
import HomePage from "./components/HomePage";

router.add("/", HomePage);
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы готовы к работе, так как закончили нашу настройку.

Промежуточное программное обеспечение маршрута

Например, посетитель не может получить доступ к приборной панели своего аккаунта, пока не войдет в систему, в таком случае мы можем использовать промежуточное ПО.

В файле src/apps/front-office/account/routes.ts мы можем определить наши маршруты следующим образом:

// src/apps/front-office/account/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./components/DashboardPage";
import EditProfilePage from "./components/EditProfilePage";
import OrderHistoryPage from "./components/OrderHistoryPage";
import SingleOrderHistoryPage from "./components/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

router.add("/account", AccountDashboardPage, [Guardian]);
router.add("/account/edit-profile", EditProfilePage), [Guardian];
router.add("/account/order-history", OrderHistoryPage, [Guardian]);
router.add("/account/order-history/:id", SingleOrderHistoryPage, [Guardian]);
Вход в полноэкранный режим Выйти из полноэкранного режима

Здесь мы определили наши маршруты, с новым аргументом в router.add, который представляет собой массив промежуточных элементов, которые будут объявлены перед переходом на наши страницы.

Теперь давайте посмотрим на наш новый файл промежуточного ПО Guardian.

// src/apps/front-office/account/middleware/Guardian.tsx
import user from "somewhere-in-the-app";
import React from "react";
import { Redirect } from "@mongez/react-router";

export default function Guardian() {
  if (user.isNotLoggedIn()) {
    return <Redirect to="/login" />;
  }

  return null;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы определили компонент, который позволяет нам проверить, не вошел ли пользователь в систему, затем мы перенаправим пользователя на маршрут входа, используя компонент Redirect из MRR.

Теперь, когда пользователь попадает на любой из маршрутов учетных записей, сначала будет вызван компонент Guardian, если пользователь не вошел в систему, то вместо компонента страницы будет вызван компонент перенаправления.

Если промежуточное ПО вернуло значение, то оно будет отображено вместо компонента страницы.

Таким образом, промежуточное ПО может выглядеть следующим образом:

// src/apps/front-office/account/middleware/Guardian.tsx
import user from "somewhere-in-the-app";
import React from "react";

export default function Guardian() {
  if (user.isNotLoggedIn()) {
    return <h1>You do not have access to this page, please login first.</h1>;
  }

  return null;
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Группированные маршруты

Поскольку мы можем использовать метод router.add для определения маршрута, мы можем определить один или несколько маршрутов с общими параметрами, такими как префикс или промежуточное ПО.

В нашем предыдущем примере с промежуточным ПО мы видим, что все маршруты начинаются с /account и все они имеют одинаковое промежуточное ПО, мы можем сгруппировать эти маршруты в один метод, используя метод router.group.

// src/apps/front-office/account/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./components/DashboardPage";
import EditProfilePage from "./components/EditProfilePage";
import OrderHistoryPage from "./components/OrderHistoryPage";
import SingleOrderHistoryPage from "./components/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

router.group({
  path: "/account",
  middleware: [Guardian],
  routes: [
    {
      path: "/",
      component: AccountDashboardPage,
    },
    {
      path: "/edit-profile",
      component: EditProfilePage,
    },
    {
      path: "/order-history",
      component: OrderHistoryPage,
    },
    {
      path: "/order-history/:id",
      component: SingleOrderHistoryPage,
    },
  ],
});
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь наш код стал компактнее и чище, также вы можете передать дополнительное промежуточное ПО любому объекту маршрута, если хотите добавить больше промежуточного ПО к определенным маршрутам.

Префикс в методе group будет склеен со всеми маршрутами в массиве routes, поэтому маршрут AccountDashboardPage будет /account/, но последние / будут обрезаны MRR.

Вы можете задать путь AccountDashboardPage в виде пустой строки » это тоже работает.

Базовый макет страницы

Большинство приложений имеют одинаковую структуру макета, такую как верхний и нижний колонтитулы, среди которых находится содержимое страницы.

Это можно легко сделать с помощью MRR, используя метод router.partOf.

// src/apps/front-office/components/BaseLayout.tsx

import React from "react";
import Header from "./Header";
import Footer from "./Footer";

export default function BaseLayout({ children }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь давайте добавим наш новый базовый макет на нашу Домашнюю страницу.

// src/apps/front-office/home/routes.ts

import router from "@mongez/router";
import HomePage from "./components/HomePage";
import BaseLayout from "apps/front-office/components/BaseLayout";

router.partOf(BaseLayout, [
  {
    path: "/",
    component: HomePage,
  },
]);
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь нашему компоненту HomePage не нужно вызывать верхний или нижний колонтитул страницы, теперь он является частью BaseLayout.

Это может быть полезно и для router.group, мы можем установить общий макет для списка страниц.

Давайте вернемся к нашему модулю счета.

// src/apps/front-office/account/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./components/DashboardPage";
import EditProfilePage from "./components/EditProfilePage";
import OrderHistoryPage from "./components/OrderHistoryPage";
import SingleOrderHistoryPage from "./components/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

import BaseLayout from "apps/front-office/components/BaseLayout";

router.group({
  path: "/account",
  layout: BaseLayout,
  middleware: [Guardian],
  routes: [
    {
      path: "/",
      component: AccountDashboardPage,
    },
    {
      path: "/edit-profile",
      component: EditProfilePage,
    },
    {
      path: "/order-history",
      component: OrderHistoryPage,
    },
    {
      path: "/order-history/:id",
      component: SingleOrderHistoryPage,
    },
  ],
});
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы добавили новое свойство в объект group под названием layout, которое определяет макет, который будет отображать все страницы маршрутов.

Расширение базового макета

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

// src/apps/front-office/account/components/AccountLayout.tsx
import React from "react";
import Header from "apps/front-office/components/Header";
import Header from "apps/front-office/components/Footer";
import AccountSidebar from "./AccountSidebar";

export default function AccountLayout({ children }) {
  return (
    <>
      <Header />
      <main>
        <AccountSidebar />
        <div>{children}</div>
      </main>
      <Footer />
    </>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь давайте снова перейдем к маршрутам нашего аккаунта, чтобы использовать наш новый макет вместо базового.

// src/apps/front-office/account/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./components/DashboardPage";
import EditProfilePage from "./components/EditProfilePage";
import OrderHistoryPage from "./components/OrderHistoryPage";
import SingleOrderHistoryPage from "./components/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

import AccountLayout from "./components/AccountLayout";

router.group({
  path: "/account",
  layout: AccountLayout,
  middleware: [Guardian],
  routes: [
    {
      path: "/",
      component: AccountDashboardPage,
    },
    {
      path: "/edit-profile",
      component: EditProfilePage,
    },
    {
      path: "/order-history",
      component: OrderHistoryPage,
    },
    {
      path: "/order-history/:id",
      component: SingleOrderHistoryPage,
    },
  ],
});
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы почти закончили, осталось расширить наш базовый макет, поскольку мы снова ввели верхний и нижний колонтитулы в компонент AccountLayout, давайте это исправим.

// src/apps/front-office/account/components/AccountLayout.tsx
import React from "react";
import BaseLayout from "apps/front-office/components/BaseLayout";
import AccountSidebar from "./AccountSidebar";

export default function AccountLayout({ children }) {
  return (
    <BaseLayout>
      <AccountSidebar />
      <div>{children}</div>
    </BaseLayout>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь наш код очень аккуратен и может легко поддерживаться.

Относительность маршрутов

Все маршруты, определенные внутри файлов routes.ts в режиме ленивой загрузки, имеют префикс пути к приложению, поэтому если у нас есть маршрут в админке, например /admin/login, то определенный маршрут в src/apps/admin/administrators/routes.ts будет /login без добавления /admin в начале.

// src/apps/admin/administrators/routes.ts

import LoginPage from "./components";
import router from "@mongez/react-router";

// here we'll define the route as /login not /admin/login
router.add("/login", LoginPage);
Вход в полноэкранный режим Выход из полноэкранного режима

Структура пути маршрута

Основываясь на конфигурациях приложений, мы создали X структур маршрутов.

Таким образом, наша полная структура маршрута будет выглядеть примерно так:

/localeCode(optional)/app-path/route

Когда вы определяете маршрут, не добавляйте путь приложения или код локали, например:

Конфигурации маршрутизаторов

MRR не требует установки каких-либо конфигураций, но рекомендуется определить некоторые конфигурации, например, код локали, используемый в проекте.

В директории src/shared создадим новый файл config.ts.

// src/shared/config.ts
import { setRouterConfigurations } from "@mongez/react-router";

setRouterConfigurations({
  // if your app is multilingual then define all locale codes in the app
  localeCodes: ["en", "ar"],
  // if the production build will be in a directory and not the root, then define the directory path in basePath
  basePath: "/",
});
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь импортируем файл в индексный файл.

// src/index.ts

// its important to import the config file before any route functions.
import "./shared/config";
import "./shared/apps-list";
import router from "@mongez/react-router";

router.scan();
Войти в полноэкранный режим Выход из полноэкранного режима

Если вы используете Mongez React, это может быть частью конфигураций всего приложения.

Вот полный список доступных конфигураций

/**
 * Router configuration options list
 */
type RouterConfigurations = {
  /**
   * Default locale code
   */
  defaultLocaleCode?: string;
  /**
   * Locale codes list
   */
  localeCodes?: string[];
  /**
   * Router preloader that will be displayed until the module is loaded
   *
   * @default React.Fragment
   */
  preloader?: React.ComponentType<any>;
  /**
   * If set to true, the current layout will not be unmounted and the preloader (if set) will be displayed before it
   * Please note the of the base layout and the preloader will have position `relative`
   * This feature is still experimental and can be changed in future versions
   * @experimental
   * @default false
   */
  preloadOverlay?: boolean;
  /**
   * App base path in production
   *
   * @default: /
   */
  basePath?: string;
  /**
   * Determine whether to re-render the page
   * When navigating to any page, even same current page
   *
   * Please note that can not be changed during the application is running
   * as its value is cached at the application bootstrap
   *
   * @default: true
   */
  forceRefresh?: boolean;
  /**
   * Scroll to top of the page when rendering new page
   *
   * @default true
   */
  scrollTop?: boolean;
  /**
   * Top Root component that will wrap the entire application regardless the lazy module
   */
  rootComponent?: React.ComponentType<any>;
  /**
   * NotFound Options
   */
  notFound?: {
    /**
     * Not found mode
     * The redirect mode will redirect the client to the path
     *
     * Please note that can not be changed during the application is running
     * as its value is cached at the application bootstrap
     *
     * @default: render
     */
    mode?: "redirect" | "render";
    /**
     * The route that will be redirected when the page is not found
     * Works only when the mode is set to redirect
     *
     * @default: /404
     */
    route?: string;
    /**
     * The component that will be rendered when the page is not found
     * Works only when the mode is set to render
     *
     * @default: React.Fragment
     */
    component?: React.ComponentType<any>;
  };
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Корневой компонент

Корневой компонент будет обертывать все приложение, независимо от того, загружается ли текущий маршрут в ленивом режиме или нет.

Корневой компонент не получает никаких реквизитов вообще.

Использование компонента Link в react предоставляет некоторые интересные возможности, чтобы сделать ссылку более читаемой и удобной в использовании.

// src/apps/front-office/home/components/HomePage.tsx
import React from "react";
import { Link } from "@mongez/react";

export default function HomePage() {
  return (
    <div>
      <Link to="/account">Go To Account Page</Link>
    </div>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Проще говоря, простая навигация по маршруту с помощью реквизита to или href.

Чтобы перейти к маршруту в новой вкладке:

<Link to="/account" newTab>
  Go To Account Page In New Tab
</Link>
// outputs: <a href="/account" target="_blank" rel="noopener noreferrer">
Войти в полноэкранный режим Выйти из полноэкранного режима

Чтобы перейти к маршруту в другой локали, введите код:

Чтобы перейти к маршруту в другом приложении:

<Link to="/customers/100" app="admin">
  Go To Customer page in admin app.
</Link>

// outputs: /admin/customers/100
Войти в полноэкранный режим Выйти из полноэкранного режима
<Link to="/account" localeCode="ar">
  Go To Account Page With Arabic Locale Code
</Link>
// outputs: /ar/account
Войти в полноэкранный режим Выйти из полноэкранного режима

Переход к другому приложению с кодом локали

<Link to="/account" app="admin" localeCode="ar">
  Go To Account Page In Admin App With Arabic Locale Code
</Link>
// outputs: /ar/admin/account
Войти в полноэкранный режим Выйти из полноэкранного режима

Реквизит app принимает имя приложения, а не путь к нему.

Чтобы перейти к url, просто задайте url :p.

<Link to="https://google.com">Go To Google</Link>
Войти в полноэкранный режим Выйти из полноэкранного режима

Сделать ссылку в виде электронной почты:

<Link mailTo="hassanzohdy@gmail.com">Email As Link</Link>
// outputs: <a href="mailto:hassanzohdy@gmail.com" .. />
Войти в полноэкранный режим Выйти из полноэкранного режима

или используя компонент MailLink напрямую

import { MailLink } from "@mongez/react-router";

<MailLink to="hassanzohdy@gmail.com">Email As Link</MailLink>;
// outputs: <a href="mailto:hassanzohdy@gmail.com" .. />
Войти в полноэкранный режим Выйти из полноэкранного режима

Сделайте ссылку в виде телефонного номера:

<Link tel="+201002221122">Phone Number As Link</Link>
// outputs: <a href="tel:+201002221122" .. />
Войти в полноэкранный режим Выйти из полноэкранного режима

или используя компонент MailLink напрямую

import { TelLink } from "@mongez/react-router";

<TelLink to="+201002221122">Phone Number As Link</TelLink>;
// outputs: <a href="tel:+201002221122" .. />
Войти в полноэкранный режим Выйти из полноэкранного режима

Конечно, вы можете отправить любые другие реквизиты html, такие как className, id и так далее.

Использовать внешнюю ссылку

import { ExternalLink } from "@mongez/react-router";

<ExternalLink to="https://google.com">Google</ExternalLink>;
// outputs: <a href="https://google.com">Google</a>
Войти в полноэкранный режим Выйти из полноэкранного режима

Открыть в новой вкладке

import { ExternalLink } from "@mongez/react-router";

<ExternalLink newTab to="https://google.com">
  Google
</ExternalLink>;
// outputs: <a target="_blank" rel="noopener noreferrer" href="https://google.com">Google</a>
Войти в полноэкранный режим Выйти из полноэкранного режима

Компонент перенаправления

Этот компонент обычно используется с промежуточным ПО, как упоминалось ранее в разделе «Промежуточное ПО».

// src/apps/admin/account/middleware/Guardian.tsx
import user from "somewhere-in-the-app";
import React from "react";
import { Redirect } from "@mongez/react-router";

export default function Guardian() {
  if (user.isNotLoggedIn()) {
    return <Redirect to="/login" localeCode="fr" app="admin" />;
  }

  return null;
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Предыдущий опекун перейдет к /admin/fr/login, так как путь к приложению admin/admin, после него добавляется код локали и, наконец, сам маршрут.

Структура маршрутов

Существует 4 типа маршрутов, для наглядности рассмотрим маршрут /login.

  1. Маршрут в базовом приложении: конечный маршрут: /login, который построен как page-route.
  2. Маршрут в базовом приложении с кодом локали: final route: /login, который строится как /locale-code/page-route.
  3. Маршрут в другом приложении, например, admin: /admin/login, который строится как /app-path/page-route.
  4. Маршрут в другом приложении с кодом локали, например admin: /admin/ar/login, который строится как /app-path/locale-code/page-route.

Получение параметров маршрутизатора

Давайте возьмем сложный маршрут и посмотрим, как мы можем принимать его значения.

Наш путь маршрута будет таким: /admin/en/customers/101 и будет отображаться в компоненте CustomerPage.

Этот путь маршрута определен как /customers/:id.

// src/apps/admin/customers/routes.ts

import router from "@mongez/react-router";
import CustomerPage from "./components/CustomerPage";

router.add("/customers/:id", CustomerPage);
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь перейдем к нашему компоненту CustomerPage.

// src/apps/admin/customers/components/CustomerPage.tsx

import React from "react";

export default function CustomerPage({ params }) {
  const { localeCode, id } = params;
  console.log(localeCode); // en
  console.log(id); // 101

  return <div>// component content</div>;
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Сегмент /admin будет проигнорирован, мы можем получить только localeCode, который определяется MRR внутренне, а наш определенный сегмент /:id преобразуется в id из объекта params.

Дикая карта маршрута

Давайте рассмотрим другой сценарий, в котором у нас есть динамические маршруты, например:

/categories/electronics/smart-phones/tablets

Маршрут определяет дерево категорий, поскольку мы будем обращаться к странице категории планшетов.

В этом смысле маршрут может быть чем-то другим, например /categories/electronics/smart-phones, где мы перейдем к категории Smart Phones.

Для получения динамического маршрута мы можем использовать подстановочные знаки.

// src/apps/front-office/categories/routes.ts

import router from "@mongez/react-router";
import CategoryPage from "./components/CategoryPage";

router.add("/categories/:slug(.+)", CategoryPage);
Войти в полноэкранный режим Выход из полноэкранного режима

В нашем компоненте CategoryPage

// src/apps/front-office/categories/components/CategoryPage.tsx

import React from "react";

export default function CategoryPage({ params }) {
  const { slug } = params;
  console.log(slug); // /electronics/smart-phones

  return <div>// component content</div>;
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы также можете использовать помощник dynamicSegment для большей читабельности.

// src/apps/front-office/categories/routes.ts

import router, { dynamicSegment } from "@mongez/react-router";
import CategoryPage from "./components/CategoryPage";

router.add("/categories/" + dynamicSegment("slug"), CategoryPage);
Вход в полноэкранный режим Выйти из полноэкранного режима

Достигнет того же результата.

Более ограниченные сегменты маршрута

Иногда сегменты, такие как :id, обычно содержат только целые числа, поэтому мы можем определить маршрут, который принимает только целые значения в маршруте, чтобы нам не пришлось делать еще один шаг проверки на заданный id, мы можем использовать помощник integerSegment.

// src/apps/admin/customers/routes.ts

import router, { integerSegment } from "@mongez/react-router";
import CustomerPage from "./components/CustomerPage";

router.add("/customers/" + integerSegment("id"), CustomerPage);
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, если пользователь перейдет по ссылке /customers/some-text, он будет автоматически перенаправлен на страницу not found, хотя маршрут /customers/101 будет действительным.

Другая вспомогательная функция floatSegment может быть использована для значений с плавающей точкой.

Переключение на другой код локали

Мы можем переключиться на другой код локали с помощью функции switchLang.

import { switchLang } from '@mongez/react-router';

import React from 'react'

export default function Header() {
  const onClick = e => {
    switchLang('ar'); // refreshes the page and changes the locale code
  };

  return (
    <div>
      <button onClick={changeLocaleCode}>Switch To Arabic<button>
    </div>
  )
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Переход к маршруту

Функция navigateTo является одной из самых мощных функций, позволяющих перейти на другую страницу.

import { navigateTo } from "@mongez/react-router";

import React from "react";

export default function CreateAccountPage() {
  const createAccount = (e) => {
    axios.post("/register", { email, password }).then((response) => {
      navigateTo("/home");
    });
  };

  return (
    <div>
      <form onSubmit={createAccount}>
        ...
        <button>Create a new account</button>
      </form>
    </div>
  );
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Переход с помощью кода локали

navigateTo("/login", "en"); // /en/login
Войти в полноэкранный режим Выйти из полноэкранного режима

Переход к маршруту с кодом локали и приложения.

navigateTo("/login", "en", "admin"); // /admin/en/login
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что третий аргумент принимает имя приложения, а не путь к нему, если вы хотите использовать путь к приложению, просто добавьте его в первый аргумент.
Если проект имеет несколько кодов локали, то при навигации с помощью функции navigateTo будет добавляться код локали, например navigateTo('/login') и код локали по умолчанию en, это приведет к навигации на /en/login.

Переход назад

import { navigateBack } from "@mongez/react-router";

import React from "react";

export default function LoginPage() {
  const login = (e) => {
    axios.post("/login", { email, password }).then((response) => {
      navigateBack();
    });
  };

  return (
    <div>
      <form onSubmit={login}>
        ...
        <button>Login</button>
      </form>
    </div>
  );
}
Войти в полноэкранный режим Выйти из полноэкранного режима

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

Обновление страницы

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

import { refresh } from '@mongez/react-router';

import React from 'react'

export default function Header() {
  const refreshPage = () => {
    refresh();
  }

  return (
    <div>
      <button onClick={refreshPage}>Refresh The Page<button>
    </div>
  )
}
Вход в полноэкранный режим Выход из полноэкранного режима

Получение маршрута текущей страницы

Для получения маршрута текущей страницы можно использовать функцию currentRoute.

// src/apps/front-office/front-office-provider.ts
import { currentRoute } from "@mongez/react-router";

// detect current route
console.log(currentRoute()); // will be something like /login or /account
Войти в полноэкранный режим Выйти из полноэкранного режима

Получение полного url страницы

Чтобы получить полный путь к странице, можно использовать функцию url.

// src/apps/front-office/front-office-provider.ts
import { url } from "@mongez/react-router";

// detect current route
console.log(url()); // will be something like https://sitename.com/online-store/account
Вход в полноэкранный режим Выход из полноэкранного режима

Конкатенация маршрутов

Иногда вам может понадобиться объединить несколько маршрутов в один маршрут, например, добавить маршрут из переменной в другую переменную, чтобы создать совершенно новый маршрут. К счастью, вы можете использовать вспомогательную функцию concatRoute, которая сделает это за вас.

import { concatRoute } from "@mongez/react-router";

const localeCode = "ar";

const route = "login";

const appPath = "/admin";

const fullRoutePath = concatRoute(appPath, localeCode, route); // /admin/ar/login
Вход в полноэкранный режим Выйти из полноэкранного режима

Каждый аргумент может начинаться с косой чертой или без нее, также любые удвоенные косые черты будут преобразованы в одну косую черту, а если есть конечная косая черта, то она также будет обрезана.

import { concatRoute } from "@mongez/react-router";

const localeCode = "ar";

const route = "//login//";

console.log(localeCode, route); // /ar/login
Войти в полноэкранный режим Выход из полноэкранного режима

Обновление строки запроса

Мы также можем обновить строку запроса в url с/без перехода к маршруту с новой строкой запроса, используя вспомогательную функцию updateQueryString. Это может быть полезно в таких случаях, как фильтрация, поскольку мы можем обновить только маршрут без полного повторного рендеринга страницы.

import { updateQueryString } from "@mongez/react-router";

export default function FilterData() {
  const filter = (e) => {
    // Just dummy data for demo only
    const filterData = {
      name: "",
      email: "",
      age: 0,
      published: true,
    };

    axios.get("/filter", filterData).then((response) => {
      updateQueryString(filterData);
    });
  };

  return (
    <div>
      <form onSubmit={filter}>
        ...
        <button>Filter</button>
      </form>
    </div>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Если мы хотим перейти на ту же страницу с обновленной строкой запроса, мы можем установить второй аргумент в true.

import { updateQueryString } from "@mongez/react-router";

export default function FilterData() {
  const filter = (e) => {
    // Just dummy data for demo only
    const filterData = {
      name: "",
      email: "",
      age: 0,
      published: true,
    };

    axios.get("/filter", filterData).then((response) => {
      updateQueryString(filterData, true); // update and navigate
    });
  };

  return (
    <div>
      <form onSubmit={filter}>
        ...
        <button>Filter</button>
      </form>
    </div>
  );
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Получение текущего хэш-значения в url

Если в url есть значение #hash, мы можем получить его с помощью вспомогательной функции hash.

import { hash } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products/10#comments

console.log(hash()); // comments
Войти в полноэкранный режим Выход из полноэкранного режима

Чтобы получить значение с хэшем, передайте функции аргумент со значением true.

import { hash } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products/10#comments

console.log(hash(true)); // #comments
Войти в полноэкранный режим Выйти из полноэкранного режима

Получение строки запроса

Чтобы получить значение из строки запроса, мы можем использовать вспомогательную функцию queryString, эта функция возвращает три внутренних метода.

Чтобы получить значение ключа из строки запроса, можно использовать метод get:

import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

console.log(queryString().get("sortBy")); // price

console.log(queryString().get("categoryId")); // 10
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что если вы собираетесь получить несколько значений из строки запроса, инициируйте queryString() в переменной, а затем используйте эту переменную.

import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

const params = queryString();

console.log(params.get("sortBy")); // price
console.log(params.get("categoryId")); // 10
Вход в полноэкранный режим Выйти из полноэкранного режима

Вы также можете получить значение по умолчанию, если параметр запроса не существует в url.

import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

const params = queryString();

console.log(params.get("sortBy")); // price

console.log(params.get("sortDirection", "desc")); // desc
Вход в полноэкранный режим Выйти из полноэкранного режима

Чтобы получить все параметры строки запроса в объекте, можно использовать метод all.

import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

console.log(queryString().all()); // {sortBy: price, categoryId: 10}
Войти в полноэкранный режим Выйти из полноэкранного режима

Чтобы получить его в виде строки, используйте метод toString.

import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

console.log(queryString().toString()); // sortBy=price&categoryId=10
Войти в полноэкранный режим Выход из полноэкранного режима

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

// src/front-office/products/components/ProductsListPage.tsx
import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

console.log(queryString().toString()); // sortBy=price&categoryId=10
import React from "react";

export default function ProductsListPage() {
  const params = queryString();

  console.log(params.get("sortBy")); // price

  // Or you can cache its value when navigating to the products list each time
  const params = React.useMemo(() => queryString(), []);
  return <div>//</div>;
}
Вход в полноэкранный режим Выйти из полноэкранного режима

// src/front-office/products/components/ProductsListPage.tsx
import { queryString } from "@mongez/react-router";

// if the url is something like https://site-name.com/online-store/products?sortBy=price&categoryId=10

console.log(queryString().toString()); // sortBy=price&categoryId=10
import React from "react";

const params = queryString();

export default function ProductsListPage() {
  console.log(params.get("sortBy")); // empty string

  return <div>//</div>;
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Получение базового url проекта

Чтобы получить базовый url, импортируйте вспомогательную функцию baseUrl, которая получит путь к домену с суффиксом basePath, определенный в разделе конфигурации маршрутизатора.

import { baseUrl } from "@mongez/react-router";

console.log(baseUrl()); // something like https://sitename.com/online-store where /online-store is the basePath of the project.
Вход в полноэкранный режим Выход из полноэкранного режима

Получить текущее направление страницы

Для получения текущего направления страницы используйте хелпер currentDirection.

currentDirection(): string

import { currentDirection } from "@mongez/react-router";

console.log(currentDirection()); // ltr for example
Вход в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что эта утилита зависит от свойства document.documentElement dir, если оно не установлено, то по умолчанию будет возвращено ltr.

Direction Is

Проверяет, совпадает ли текущее направление с заданным, используя утилиту directionIs.

directionIs(direction: 'ltr' | 'rtl'): boolean

import { directionIs } from "@mongez/react-router";

console.log(directionIs("ltr")); // true
console.log(directionIs("rtl")); // false
Войти в полноэкранный режим Выход из полноэкранного режима

Получить предыдущий маршрут

Для получения предыдущего маршрута используйте функцию previousRoute.

import { previousRoute, navigateTo } from "@mongez/react-router";
navigateTo("/login");
console.log(previousRoute()); // /
navigateTo("/");
console.log(previousRoute()); // /login
Войти в полноэкранный режим Выйти из полноэкранного режима

События маршрутизатора

Вы можете прослушать любое изменение маршрутизатора, основанное на изменении навигационной ссылки.

import { routerEvents } from "@mongez/react-router";

routerEvents.onChange(() => {
  // route changed
});
Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

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

Для получения дополнительной документации просмотрите репозиторий Github.

Не стесняйтесь присылать мне свои отзывы.

Оцените статью
devanswers.ru
Добавить комментарий