Skip to content

Commit 54df3a3

Browse files
committed
fix(router): rework improper lifecycle in context
1 parent 47c27fc commit 54df3a3

File tree

3 files changed

+33
-13
lines changed

3 files changed

+33
-13
lines changed

src/lib/components/RouterContext.svelte

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
import type { RouterContextProps } from '~/models/component.model.js';
33
import type { IRouter } from '~/models/router.model.js';
44
5+
import { onDestroy, onMount } from 'svelte';
6+
57
import { getRouter, setRouter } from '~/router/context.svelte.js';
6-
import { Router } from '~/router/router.svelte.js';
78
import { Logger, LoggerKey } from '~/utils/logger.utils.js';
89
910
const { children, router, options }: RouterContextProps = $props();
@@ -17,21 +18,21 @@
1718
});
1819
}
1920
20-
const createInnerRouter = (_router: IRouter = new Router(options)) => {
21-
setRouter(_router);
21+
const resolveRouter = () => {
22+
if (outerRouter) return outerRouter;
23+
const _router = setRouter(router, options);
2224
Logger.debug(`[${LoggerKey} Context]`, 'Router Context set:', _router);
2325
return _router;
2426
};
2527
26-
const innerRouter: IRouter | undefined = outerRouter ? undefined : createInnerRouter(router);
27-
const resolvedRouter: IRouter = (outerRouter ?? innerRouter)!;
28-
29-
$effect.pre(() => {
30-
if (!innerRouter || innerRouter.ready) return;
31-
innerRouter.init();
28+
const resolvedRouter: IRouter = resolveRouter();
3229
33-
return () => innerRouter?.destroy();
30+
onMount(() => {
31+
if (resolvedRouter?.ready) return;
32+
resolvedRouter?.init();
3433
});
34+
35+
onDestroy(() => resolvedRouter?.destroy());
3536
</script>
3637

3738
{#if resolvedRouter}

src/lib/router/context.svelte.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import type { RouteName } from '~/models/route.model.js';
2-
import type { IRouter } from '~/models/router.model.js';
2+
import type { IRouter, RouterOptions } from '~/models/router.model.js';
33
import type { IView } from '~/models/view.model.js';
44

55
import { getContext, setContext } from 'svelte';
66

7+
import { Router } from '~/router/router.svelte.js';
8+
79
export const RouterContextSymbol = Symbol('SvelteSimpleRouterContext');
810
export const RouterViewSymbol = Symbol('SvelteSimpleRouterView');
911

1012
export function getRouter<Name extends RouteName = any>(): IRouter<Name> | undefined {
1113
return getContext<IRouter<Name>>(RouterContextSymbol);
1214
}
1315

14-
export function setRouter<Name extends RouteName = any>(router: IRouter<Name>): IRouter<Name> {
15-
return setContext(RouterContextSymbol, router);
16+
export function setRouter<Name extends RouteName = any>(router?: IRouter<Name>, options?: RouterOptions<Name>): IRouter<Name> {
17+
return setContext(RouterContextSymbol, router ?? new Router(options));
1618
}
1719

1820
export function getView<Name extends RouteName = any>(): IView<Name> {

test/components/components.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ describe('routerView', () => {
5555

5656
describe('routing', () => {
5757
const common = (component: typeof RouteView | typeof RouterContext | typeof RouterViewNested) => {
58+
it('should initialize external router on mount and destroy on unmounted', async () => {
59+
expect.assertions(4);
60+
const localRouter = new Router({ routes });
61+
const spyInit = vi.spyOn(localRouter, 'init');
62+
const spyDestroy = vi.spyOn(localRouter, 'destroy');
63+
64+
const result = render(component, { router: localRouter });
65+
66+
expect(spyInit).toHaveBeenCalledTimes(1);
67+
expect(spyDestroy).not.toHaveBeenCalled();
68+
69+
result.unmount();
70+
71+
expect(spyDestroy).toHaveBeenCalledTimes(1);
72+
expect(spyInit).toHaveBeenCalledTimes(1);
73+
});
74+
5875
it('should render no component', () => {
5976
expect.assertions(4);
6077
render(component, { router });

0 commit comments

Comments
 (0)