Skip to content

Commit 394bd76

Browse files
committed
fix: Nested routing
1 parent cd2e5f2 commit 394bd76

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

src/router.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { h, Fragment, createContext, cloneElement, toChildArray } from 'preact';
1+
import { h, createContext, cloneElement, toChildArray } from 'preact';
22
import { useContext, useMemo, useReducer, useLayoutEffect, useRef } from 'preact/hooks';
33

44
/**
@@ -137,6 +137,7 @@ export function Router(props) {
137137
if (!url) {
138138
throw new Error(`preact-iso's <Router> must be used within a <LocationProvider>, see: https://github.com/preactjs/preact-iso#locationprovider`);
139139
}
140+
const { rest = path } = useContext(RouterContext);
140141

141142
const isLoading = useRef(false);
142143
const prevRoute = useRef(path);
@@ -156,7 +157,7 @@ export function Router(props) {
156157

157158
let pathRoute, defaultRoute, matchProps;
158159
toChildArray(props.children).some((/** @type {VNode<any>} */ vnode) => {
159-
const matches = exec(path, vnode.props.path, (matchProps = { ...vnode.props, path, pathParams, searchParams }));
160+
const matches = exec(rest, vnode.props.path, (matchProps = { ...vnode.props, path: rest, pathParams, searchParams }));
160161
if (matches) return (pathRoute = cloneElement(vnode, matchProps));
161162
if (vnode.props.default) defaultRoute = cloneElement(vnode, matchProps);
162163
});
@@ -169,7 +170,7 @@ export function Router(props) {
169170
const routeChanged = useMemo(() => {
170171
prev.current = cur.current;
171172

172-
cur.current = /** @type {VNode<any>} */ (h(Fragment, { key: path }, incoming));
173+
cur.current = /** @type {VNode<any>} */ (h(RouterContext.Provider, { value: matchProps }, incoming));
173174

174175
// Only mark as an update if the route component changed.
175176
const outgoing = prev.current && prev.current.props.children;
@@ -283,6 +284,9 @@ Router.Provider = LocationProvider;
283284
LocationProvider.ctx = createContext(
284285
/** @type {import('./router.d.ts').LocationHook & { wasPush: boolean }} */ ({})
285286
);
287+
const RouterContext = createContext(
288+
/** @type {{ rest: string }} */ ({})
289+
);
286290

287291
export const Route = props => h(props.component, props);
288292

test/router.test.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -855,8 +855,8 @@ describe('Router', () => {
855855
const Inner = () => (
856856
<Router>
857857
<Route
858-
path="/bob"
859-
component={() => null}
858+
path="/baz"
859+
component={() => <h1>Baz</h1>}
860860
/>
861861
</Router>
862862
);
@@ -866,15 +866,16 @@ describe('Router', () => {
866866
<Router>
867867
<Route path="/foo/:id/*" component={Inner} />
868868
</Router>
869-
<a href="/foo/bar/bob"></a>
869+
<a href="/foo/bar/baz"></a>
870870
<ShallowLocation />
871871
</LocationProvider>,
872872
scratch
873873
);
874874

875-
scratch.querySelector('a[href="/foo/bar/bob"]').click();
875+
scratch.querySelector('a[href="/foo/bar/baz"]').click();
876876
await sleep(1);
877-
expect(loc).to.deep.include({ path: '/foo/bar/bob', pathParams: { id: 'bar' }, searchParams: {} });
877+
expect(loc).to.deep.include({ path: '/foo/bar/baz', pathParams: { id: 'bar' }, searchParams: {} });
878+
expect(scratch).to.have.property('textContent', 'Baz');
878879
});
879880

880881
it('should append params in nested routes', async () => {

0 commit comments

Comments
 (0)