Как стать автором
Обновить

Продвинутое использование библиотеки React Router v7: как упростить сложную навигацию и улучшить производительность

Уровень сложностиСредний
Время на прочтение9 мин
Количество просмотров5.5K
Всего голосов 6: ↑6 и ↓0+6
Комментарии8

Комментарии 8

Любопытно стало, а почему решили не использовать декларативный подход? Что-то типа:

<Routes>
  <Route component={AppLayout}>
    <Route path="not-found-page-path" component="..." />
    <Route component={LayoutNeedExtension}>
      <Route path="..." component={...} />
    </Route>
  </Route>
</Routes>

И общую логику выносить, например, в соответствующие каркасные маршруты?

Да и формат path тоже упрощается.

Правды ради отмечу, что изначально на проекте так и было сделано, как ты (извини за фамильярность, если что) правильно заметил, были сделаны каскадные маршруты, но вот проверка плагина реализоввалась через кастомный хук и стейт менеджер (суммарно все занимало строчек 700 😒).
Поэтому немного покопавшись в возможностях react-router - попробовали переписать - и по части кода стало гораздо чище (раза в 3 меньше объема), да и доп. фукционал в виде loader, action - которые доступны только в таком виде через createBrowserRouter прекрасно подошел под наши потребности.

Что касается формата path и указания element вместо компонент, то тут ничего ведь не поменялось, просто немного непривычная форма записи) - а когда поработаешь с ней 0 то children становятся как свои собственные 😁.

"как ты (извини за фамильярность, если что) ..." - да без проблем.

Я имел в виду, вот эти общие для всех проверки вынести в layout и там отрисовывать Outlet, loader, redirect и т.п. в зависимости от вашей логики.

Мне именно любопытно какие тут подводные камни.

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

Вот такие вот штуки меня, в общем-то, напрягают:

<Navigate to={`${ROUTES.stepsRootPage}/${PageSteps.Greeting}`} />
<Navigate to={`${ROUTES.stepsRootPage}/${PageSteps.ExtensionNotInstalled}`} />;

При этом у вас и внутри app-routes создаются элементы из каких-то компонентов, и внутри pages тоже создается такой же характер работы. Иными словами вот это вот дерево маршрутов размазано по файловой системе.

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

export const ROUTES = {
    mainPage: '/',
    stepsRootPage: '/steps',
    stepPage: `:${STEP_PARAMS_NAME}`,
    notFound: '/not-found',
    anyRoute: '*',
};

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

Если ты про редиректы и Layout - то в принципе здесь все это используется, только видимо тебя смутил подход через children - и кстати react-router уже 7-й версии (и по-моему 6-е последние тоже) поддерживает такой стиль написания тоже:
<BrowserRouter><Route loader={()=>true}></Route></BrowserRouter>
Поэтому на вкус и цвет как говориться)

"Вот такие вот штуки меня, в общем-то, напрягают: "
Мне кажется такая же проблема остается и при старом стиле написания, Здесь в демке также используется Layout и Outlet,ничего в этом плане нового.
И еще оговорюсь, когда мы обновляли router (изначально это была не 7-я версия) - и только в подходе с children можно было примененять loader, action -

И еще интересно с Navigate - и path в роутах, как вы у себя боретесь со сложными путями, ведь в больших структурах страниц все равно неизбежно их появление.

"Просто для примера, захотите вы сейчас добавить возможность работы вашего приложения не от корня, а от какого-нибудь публичного урла " - никто не мешает сделать так в самом простом варианте:
export const ROUTES = {
mainPage: 'EXTERNAL_URL', stepsRootPage: 'EXTERNAL_URL/steps', };

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

можно посоветовать ещё в объекте ROUTES хранить не просто константы-строки, а методы, которые возвращают полный путь до желаемой страницы

const toBlogPost: (postId: UUID) => '/blog/post/' + postId;
toBlogPost.route = ":postId";

export const ROUTES = {
  toBlogPost,
  ...
};

тогда их можно использовать и в RouteObject

export const anyRoute: RouteObject = {
  path: ROUTES.toBlogPost.route,
  Component: BlogPost,
  loader: loaderBlogPost,
  ...
};

и при навигации в проекте

 <NavLink to={ROUTES.toBlogPost(postId)}>...</NavLink>

Спасибо, можно смело что-то такое сделать - или ютилку написать для таких вещей, и я думаю наше приложение если было бы побольше, то для удобства и читаемости так бы и сделали, пока обходимся константами)

Супер, спасибо) Давно хотел попробовать с ним пет проектик, на проде у нас везде реакт роутер.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий