core-api: add naive implementation of param-relative routing
Co-authored-by: blam <ben@blam.sh>
This commit is contained in:
@@ -38,6 +38,7 @@ const ref1 = createRouteRef(mockConfig());
|
||||
const ref2 = createRouteRef(mockConfig());
|
||||
const ref3 = createRouteRef(mockConfig());
|
||||
const ref4 = createRouteRef(mockConfig());
|
||||
const ref5 = createRouteRef(mockConfig());
|
||||
|
||||
const MockRouteSource = (props: {
|
||||
name: string;
|
||||
@@ -47,7 +48,7 @@ const MockRouteSource = (props: {
|
||||
const routeFunc = useRouteRef(props.routeRef);
|
||||
return (
|
||||
<div>
|
||||
Path at {props.name}: {routeFunc?.(props.params)}
|
||||
Path at {props.name}: {routeFunc(props.params)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -64,6 +65,9 @@ const Extension3 = plugin.provide(
|
||||
const Extension4 = plugin.provide(
|
||||
createRoutableExtension({ component: MockRouteSource, mountPoint: ref4 }),
|
||||
);
|
||||
const Extension5 = plugin.provide(
|
||||
createRoutableExtension({ component: MockComponent, mountPoint: ref5 }),
|
||||
);
|
||||
|
||||
describe('discovery', () => {
|
||||
it('should handle simple routeRef path creation for routeRefs used in other parts of the app', () => {
|
||||
@@ -100,7 +104,7 @@ describe('discovery', () => {
|
||||
|
||||
it('should handle routeRefs with parameters', () => {
|
||||
const root = (
|
||||
<MemoryRouter initialEntries={['/foo/bar/:id']}>
|
||||
<MemoryRouter initialEntries={['/foo/bar/wat']}>
|
||||
<Routes>
|
||||
<Extension1 path="/foo">
|
||||
<Extension4
|
||||
@@ -141,4 +145,36 @@ describe('discovery', () => {
|
||||
rendered.getByText('Path at outside: /foo/bar/blob'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle relative routing within parameterized routes', () => {
|
||||
const root = (
|
||||
<MemoryRouter initialEntries={['/foo/blob/bar']}>
|
||||
<Routes>
|
||||
<Extension5 path="/foo/:id">
|
||||
<Extension2 path="/bar" name="inside" routeRef={ref3} />
|
||||
<Extension3 path="/baz" />
|
||||
</Extension5>
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
const { routes, routeParents } = traverseElementTree({
|
||||
root,
|
||||
discoverers: [childDiscoverer, routeElementDiscoverer],
|
||||
collectors: {
|
||||
routes: routeCollector,
|
||||
routeParents: routeParentCollector,
|
||||
},
|
||||
});
|
||||
|
||||
const rendered = render(
|
||||
<RoutingProvider routes={routes} routeParents={routeParents}>
|
||||
{root}
|
||||
</RoutingProvider>,
|
||||
);
|
||||
|
||||
expect(
|
||||
rendered.getByText('Path at inside: /foo/blob/baz'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import React, { createContext, ReactNode, useContext } from 'react';
|
||||
import { RouteRef } from './types';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { generatePath, useParams } from 'react-router-dom';
|
||||
|
||||
export type RouteFunc = (params?: Record<string, string>) => string;
|
||||
|
||||
@@ -26,7 +26,7 @@ class RouteResolver {
|
||||
private readonly routeParents: Map<RouteRef, RouteRef | undefined>,
|
||||
) {}
|
||||
|
||||
resolve(routeRef: RouteRef): RouteFunc {
|
||||
resolve(routeRef: RouteRef, parentParams: Record<string, string>): RouteFunc {
|
||||
let currentRouteRef: RouteRef | undefined = routeRef;
|
||||
let fullPath = '';
|
||||
|
||||
@@ -40,20 +40,21 @@ class RouteResolver {
|
||||
}
|
||||
|
||||
return (params?: Record<string, string>) => {
|
||||
return generatePath(fullPath, params);
|
||||
return generatePath(fullPath, { ...params, ...parentParams });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const RoutingContext = createContext<RouteResolver | undefined>(undefined);
|
||||
|
||||
export function useRouteRef(routeRef: RouteRef): RouteFunc | undefined {
|
||||
export function useRouteRef(routeRef: RouteRef): RouteFunc {
|
||||
const resolver = useContext(RoutingContext);
|
||||
const params = useParams();
|
||||
if (!resolver) {
|
||||
throw new Error('No route resolver found in context');
|
||||
}
|
||||
|
||||
return resolver.resolve(routeRef);
|
||||
return resolver.resolve(routeRef, params);
|
||||
}
|
||||
|
||||
type ProviderProps = {
|
||||
|
||||
Reference in New Issue
Block a user