core-app-api: FlatRoutes react-router stable compatibility
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
Updated `FlatRoutes` to be compatible with `react-router` v6 stable.
|
||||
@@ -18,6 +18,8 @@ import React, { ReactNode } from 'react';
|
||||
import { useRoutes } from 'react-router-dom';
|
||||
import { useApp, useElementFilter } from '@backstage/core-plugin-api';
|
||||
|
||||
let warned = false;
|
||||
|
||||
type RouteObject = {
|
||||
path: string;
|
||||
element: ReactNode;
|
||||
@@ -49,7 +51,11 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => {
|
||||
const { NotFoundErrorPage } = app.getComponents();
|
||||
const routes = useElementFilter(props.children, elements =>
|
||||
elements
|
||||
.getElements<{ path?: string; children: ReactNode }>()
|
||||
.getElements<{
|
||||
path?: string;
|
||||
element?: ReactNode;
|
||||
children?: ReactNode;
|
||||
}>()
|
||||
.flatMap<RouteObject>(child => {
|
||||
let path = child.props.path;
|
||||
|
||||
@@ -59,16 +65,30 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => {
|
||||
}
|
||||
path = path?.replace(/\/\*$/, '') ?? '/';
|
||||
|
||||
let element = child.props.element;
|
||||
if (!element) {
|
||||
element = child;
|
||||
if (!warned && process.env.NODE_ENV !== 'test') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'DEPRECATION WARNING: All elements within <FlatRoutes> must be of type <Route> with an element prop. ' +
|
||||
'Existing usages of <Navigate key=[path] to=[to] /> should be replaced with <Route path=[path] element={<Navigate to=[to] />} />',
|
||||
);
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
// Each route matches any sub route, except for the explicit root path
|
||||
path,
|
||||
element: child,
|
||||
element,
|
||||
children: child.props.children
|
||||
? [
|
||||
// These are the children of each route, which we all add in under a catch-all
|
||||
// subroute in order to make them available to `useOutlet`
|
||||
{
|
||||
path: path === '/' ? '/' : '/*', // The root path must require an exact match
|
||||
path: path === '/' ? '/' : '*', // The root path must require an exact match
|
||||
element: child.props.children,
|
||||
},
|
||||
]
|
||||
@@ -77,19 +97,19 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => {
|
||||
];
|
||||
})
|
||||
// Routes are sorted to work around a bug where prefixes are unexpectedly matched
|
||||
// TODO(Rugvip): This can be removed once react-router v6 beta is no longer supported
|
||||
.sort((a, b) => b.path.localeCompare(a.path))
|
||||
// We make sure all routes have '/*' appended, except '/'
|
||||
.map(obj => {
|
||||
obj.path = obj.path === '/' ? '/' : `${obj.path}/*`;
|
||||
return obj;
|
||||
}),
|
||||
.map(obj => ({ ...obj, path: obj.path === '/' ? '/' : `${obj.path}/*` })),
|
||||
);
|
||||
|
||||
// TODO(Rugvip): Possibly add a way to skip this, like a noNotFoundPage prop
|
||||
routes.push({
|
||||
element: <NotFoundErrorPage />,
|
||||
path: '/*',
|
||||
});
|
||||
const withNotFound = [
|
||||
...routes,
|
||||
{
|
||||
path: '/*',
|
||||
element: <NotFoundErrorPage />,
|
||||
},
|
||||
];
|
||||
|
||||
return useRoutes(routes);
|
||||
return useRoutes(withNotFound);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user