Skip to content

Commit ff9d6a7

Browse files
committed
perf: use next.js router if available
1 parent d5af17b commit ff9d6a7

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

packages/core/src/router.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
export type Callback = (newSearchParams: string) => void;
22

3+
declare global {
4+
interface Window {
5+
next?: {
6+
router?: {
7+
push: (href: string) => void;
8+
};
9+
};
10+
}
11+
}
12+
313
export interface UrlStateRouter {
414
push(href: string): void;
515

@@ -11,52 +21,58 @@ export type GenericRouterOptions = {
1121
poolingIntervalMs?: number;
1222
};
1323

14-
const subscribers = new Map<Callback, Callback>();
15-
1624
let genericRouterCurrentStateString = '';
1725
export class GenericRouter implements UrlStateRouter {
1826
private interval: number = 0;
27+
private subscribers = new Map<Callback, Callback>();
1928

2029
constructor(private options: GenericRouterOptions) {
2130
this.options = { poolingIntervalMs: 100, ...options };
2231
}
2332

2433
push(href: string): void {
25-
window.history.pushState({}, '', href);
34+
// Use Next.js router if available
35+
// Next.js exposes a global object `window.next.router` with a `push` method for both /pages and /app routes
36+
if (typeof window.next?.router?.push === 'function') {
37+
window.next.router.push(href);
38+
} else {
39+
window.history.pushState({}, '', href);
40+
}
2641
this.onSearchParamsChange();
2742
}
2843

2944
subscribe(fn: Callback): void {
30-
subscribers.set(fn, fn);
45+
this.subscribers.set(fn, fn);
3146

3247
if (!this.interval) {
3348
this.startPolling();
3449
}
3550
}
3651

3752
unsubscribe(fn: Callback): void {
38-
subscribers.delete(fn);
53+
this.subscribers.delete(fn);
3954

40-
if (subscribers.size === 0) {
55+
if (this.subscribers.size === 0) {
4156
this.stopPolling();
4257
}
4358
}
4459

4560
onSearchParamsChange(): void {
4661
if (window.location.search !== genericRouterCurrentStateString) {
4762
genericRouterCurrentStateString = window.location.search;
48-
subscribers.forEach((subscriber) =>
63+
this.subscribers.forEach((subscriber) =>
4964
subscriber(genericRouterCurrentStateString),
5065
);
5166
}
5267
}
5368

5469
private startPolling(): void {
5570
// 'popstate' event in browser is not reliable, so we need to poll
71+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent
5672
if (typeof window !== 'undefined') {
5773
this.interval = setInterval(() => {
5874
this.onSearchParamsChange();
59-
}, this.options.poolingIntervalMs) as unknown as number; // fix for NodeJS
75+
}, this.options.poolingIntervalMs) as unknown as number; // type fix for NodeJS
6076
}
6177
}
6278

0 commit comments

Comments
 (0)