Проблема с динамическими маршрутами React с микроинтерфейсами

Я создаю микро-интерфейсы с помощью React и Vite. У меня возникли проблемы с прохождением нужных мне маршрутов.

путь страница '/' домашняя страница хост-приложения '/some-tenant' TenantPage удаленного приложения '/some-tenant/some-subscription' Страница подписки на удаленное приложение

При запуске хост-приложения, которое я перехожу к "/some-tenant", ничего не появляется. Когда я перехожу к "/some-tenant/some-sub", TenantPage загружается. "/tenant/sub/test" загружает SubscriptionPage.

Я попробовал несколько вещей, чтобы заставить его работать, но сложная часть заключается в том, что я хочу использовать одни и те же маршруты при независимом запуске удаленного приложения. Есть идеи, как добиться того и другого? Вот репозиторий для воссоздания проблемы. https://github.com/lestersconyers/react-routes/

Фрагменты для справки

хост-приложение App.tsx

const RemoteRootApp = lazy(() => import('remoteApp/RemoteRootApp') as any);

function App() {
  return (
    <div className = "app">
      <React.Suspense fallback = "Loading">
        <Routes>
          <Route path = "/" element = {<HomePage />} />
          <Route path = ":tenant" element = {<RemoteRootApp />} />
          <Route path = ":tenant/*" element = {<RemoteRootApp />} />
        </Routes>
      </React.Suspense>
    </div>
  )
}

удаленное приложение App.tsx

function App() {
  return (
    <div className = "app">
      <Routes>
        <Route path = ":tenant" element = {<TenantPage />} />
        <Route path = ":tenant/:subscription" element = {<SubscriptionPage />} />
        <Route
          path = ":tenant/:subscription/manage"
          element = {<ManageSubscriptionPage />}
        />
      </Routes>
    </div>
  )
}

удаленное приложение main.tsx

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
)
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
0
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема

Если «удаленное приложение» отображается на пути маршрута "/:tenant/*" «основного приложения», то все его подмаршруты будут построены относительно этого родительского пути маршрута. Проблема в том, что «удаленное приложение» имеет дополнительный «перекрывающийся»/«дублирующий» сегмент пути «арендатора», который смешивает то, что вы ожидаете сопоставить.

Что у вас есть прямо сейчас, с отмеченными совпадающими маршрутами:

хост-приложение App.tsx

const RemoteRootApp = lazy(() => import('remoteApp/RemoteRootApp') as any);

function App() {
  return (
    <div className = "app">
      <React.Suspense fallback = "Loading">
        <Routes>
          <Route path = "/" element = {<HomePage />} />

          {/* Matches
            *   - "/some-tenant/some-sub"
            *   - "/tenant/sub/test"
            *   - "/some-tenant"
            */}
          <Route path = "/:tenant/*" element = {<RemoteRootApp />} />
        </Routes>
      </React.Suspense>
    </div>
  );
}

удаленное приложение App.tsx

function App() {
  return (
    <div className = "app">
      <Routes>
        {/* Nothing matches "/some-tenant" */}

        <Route
          // "/:tenant/:tenant" matches "/some-tenant/some-sub"
          path = ":tenant"
          element = {<TenantPage />}
        />
        <Route
          // "/:tenant/:tenant/:subscription" matches "/tenant/sub/test"
          path = ":tenant/:subscription"
          element = {<SubscriptionPage />}
        />
        <Route
          path = ":tenant/:subscription/manage"
          element = {<ManageSubscriptionPage />}
        />
      </Routes>
    </div>
  );
}

Решение

В своем «удаленном приложении» вы хотите исключить ведущий «дубликат» tenant сегмент пути.

удаленное приложение App.tsx

function App() {
  return (
    <div className = "app">
      <Routes>
        {/* Nothing matches "/tenant/sub/test" */}

        <Route
          // "/:tenant" matches "/some-tenant"
          path = "/"
          element = {<TenantPage />}
        />
        <Route
          // "/:tenant/:subscription" matches "/some-tenant/some-sub"
          path = "/:subscription"
          element = {<SubscriptionPage />}
        />
        <Route
          path = "/:subscription/manage"
          element = {<ManageSubscriptionPage />}
        />
      </Routes>
    </div>
  );
}

Когда «удаленное приложение» запускается отдельно, вы можете предоставить сегмент корневого tenant пути маршрутизатору через свойство basename, и все маршруты/ссылки/и т. д. будут функционировать относительно этого пути.

import { BrowserRouter } from 'react-rotuer-dom';

...

<BrowserRouter basename = "/some-tenant">
  {/* Remote App */}
  <RootApp />
</BrowserRouter>

Но если я это сделаю, я не смогу использовать тот же путь при независимом запуске удаленного приложения. В этом случае / окажется на странице клиента, но мне нужен арендатор из пути к местоположению.

lestersconyers 14.04.2024 18:13

@lestersconyers Почему бы вам не использовать одни и те же маршруты, они не меняются? Можете ли вы уточнить, что вы подразумеваете под «независимым запуском моего удаленного приложения»? Вы имеете в виду, что размещаете и обслуживаете удаленное приложение в другом месте, возможно, в подкаталоге?

Drew Reese 14.04.2024 18:16

Правильный. Когда мы активно разрабатываем, мы хотим воспользоваться преимуществами Vite HMR, поэтому запускаем удаленное приложение отдельно через npm run dev. Не отображается, что HMR доступен при предварительном просмотре.

lestersconyers 14.04.2024 18:21

@lestersconyers Это кажется отдельной проблемой/вопросом. Зависит ли правильность работы удаленного приложения от параметра пути tenant основного приложения? Предположительно, вы отображаете удаленное приложение в маршрутизаторе при изолированной работе, и если вам нужен этот корневой tenant сегмент пути, вы можете указать опорное имя basename на маршрутизаторе и получить доступ к удаленному приложению, как если бы оно обслуживалось из подкаталог.

Drew Reese 14.04.2024 18:41

basename делает свое дело. ``` // удаленное приложение main.tsx const tenant = window.location.pathname.split('/')[1]; ReactDOM.createRoot(document.getElementById('root')!).render‌​( <React.StrictMode> <BrowserRouter basename = {'/' + tenant} > <App /> </BrowserRouter> </React.StrictMode>, ) ```

lestersconyers 14.04.2024 20:43

Думаю, я плохо разбираюсь в ТАК, ха-ха. Я спросил, как добиться того и другого. Если вы хотите изменить свой ответ, включив в него базовое имя, это будет полезно другим. Спасибо.

lestersconyers 14.04.2024 20:45

Другие вопросы по теме