Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(react): Support root and wildcard routes in react router v6 #5971

Merged
merged 1 commit into from Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions packages/react/src/reactrouterv6.tsx
Expand Up @@ -122,13 +122,17 @@ function getNormalizedName(

const path = route.path;
if (path) {
const newPath = path[0] === '/' ? path : `/${path}`;
const newPath = path[0] === '/' || pathBuilder[pathBuilder.length - 1] === '/' ? path : `/${path}`;
pathBuilder += newPath;
if (branch.pathname === location.pathname) {
// If the route defined on the element is something like
// <Route path="/stores/:storeId/products/:productId" element={<div>Product</div>} />
// We should check against the branch.pathname for the number of / seperators
if (getNumberOfUrlSegments(pathBuilder) !== getNumberOfUrlSegments(branch.pathname)) {
if (
// If the route defined on the element is something like
// <Route path="/stores/:storeId/products/:productId" element={<div>Product</div>} />
// We should check against the branch.pathname for the number of / seperators
getNumberOfUrlSegments(pathBuilder) !== getNumberOfUrlSegments(branch.pathname) &&
// We should not count wildcard operators in the url segments calculation
pathBuilder.slice(-2) !== '/*'
) {
return [newPath, 'route'];
}
return [pathBuilder, 'route'];
Expand Down
92 changes: 92 additions & 0 deletions packages/react/test/reactrouterv6.test.tsx
Expand Up @@ -6,6 +6,7 @@ import {
matchRoutes,
MemoryRouter,
Navigate,
Outlet,
Route,
Routes,
useLocation,
Expand Down Expand Up @@ -525,5 +526,96 @@ describe('React Router v6', () => {
metadata: { source: 'route' },
});
});

it('does not add double slashes to URLS', () => {
const [mockStartTransaction, { mockSetName }] = createInstrumentation();
const wrappedUseRoutes = wrapUseRoutes(useRoutes);

const Routes = () =>
wrappedUseRoutes([
{
path: '/',
element: (
<div>
<Outlet />
</div>
),
children: [
{
path: 'tests',
children: [
{ index: true, element: <div>Main Test</div> },
{ path: ':testId/*', element: <div>Test Component</div> },
],
},
{ path: '/', element: <Navigate to="/home" /> },
{ path: '*', element: <Navigate to="/404" replace /> },
],
},
{
path: '/',
element: <div />,
children: [
{ path: '404', element: <div>Error</div> },
{ path: '*', element: <Navigate to="/404" replace /> },
],
},
]);

render(
<MemoryRouter initialEntries={['/tests']}>
<Routes />
</MemoryRouter>,
);

expect(mockStartTransaction).toHaveBeenCalledTimes(1);
// should be /tests not //tests
expect(mockSetName).toHaveBeenLastCalledWith('/tests', 'route');
});

it('handles wildcard routes properly', () => {
const [mockStartTransaction, { mockSetName }] = createInstrumentation();
const wrappedUseRoutes = wrapUseRoutes(useRoutes);

const Routes = () =>
wrappedUseRoutes([
{
path: '/',
element: (
<div>
<Outlet />
</div>
),
children: [
{
path: 'tests',
children: [
{ index: true, element: <div>Main Test</div> },
{ path: ':testId/*', element: <div>Test Component</div> },
],
},
{ path: '/', element: <Navigate to="/home" /> },
{ path: '*', element: <Navigate to="/404" replace /> },
],
},
{
path: '/',
element: <div />,
children: [
{ path: '404', element: <div>Error</div> },
{ path: '*', element: <Navigate to="/404" replace /> },
],
},
]);

render(
<MemoryRouter initialEntries={['/tests/123']}>
<Routes />
</MemoryRouter>,
);

expect(mockStartTransaction).toHaveBeenCalledTimes(1);
expect(mockSetName).toHaveBeenLastCalledWith('/tests/:testId/*', 'route');
});
});
});