Skip to content

Commit 8da8096

Browse files
authored
fix(next-app-router): better detection of route change (#6467)
1 parent 57abee4 commit 8da8096

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

packages/react-instantsearch-nextjs/src/InstantSearchNext.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { safelyRunOnBrowser } from 'instantsearch.js/es/lib/utils';
22
import { headers } from 'next/headers';
3-
import { usePathname } from 'next/navigation';
4-
import React, { useEffect, useRef } from 'react';
3+
import React, { useEffect, useMemo, useRef } from 'react';
54
import {
65
InstantSearch,
76
InstantSearchRSCContext,
@@ -21,11 +20,9 @@ import type {
2120
} from 'react-instantsearch-core';
2221

2322
const InstantSearchInitialResults = Symbol.for('InstantSearchInitialResults');
24-
const InstantSearchLastPath = Symbol.for('InstantSearchLastPath');
2523
declare global {
2624
interface Window {
2725
[InstantSearchInitialResults]?: InitialResults;
28-
[InstantSearchLastPath]?: string;
2926
}
3027
}
3128

@@ -51,11 +48,17 @@ export function InstantSearchNext<
5148
}: InstantSearchNextProps<TUiState, TRouteState>) {
5249
const isMounting = useRef(true);
5350
const isServer = typeof window === 'undefined';
54-
const pathname = usePathname();
55-
const hasRouteChanged =
56-
!isServer &&
57-
window[InstantSearchLastPath] &&
58-
window[InstantSearchLastPath] !== pathname;
51+
52+
const hasRouteChanged = useMemo(() => {
53+
// On server, always return false
54+
if (isServer) {
55+
return false;
56+
}
57+
58+
// On client, route has changed if initialResults have been cleaned up
59+
const hasInitialResults = window[InstantSearchInitialResults] !== undefined;
60+
return !hasInitialResults;
61+
}, [isServer]);
5962

6063
// We only want to trigger a search from a server environment
6164
// or if a Next.js route change has happened on the client
@@ -69,10 +72,6 @@ export function InstantSearchNext<
6972
};
7073
}, []);
7174

72-
useEffect(() => {
73-
window[InstantSearchLastPath] = pathname;
74-
}, [pathname]);
75-
7675
const nonce = safelyRunOnBrowser(() => undefined, {
7776
fallback: () => headers().get('x-nonce') || undefined,
7877
});

packages/react-instantsearch-nextjs/src/__tests__/InstantSearchNext.test.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ import { SearchBox } from 'react-instantsearch';
1010

1111
import { InstantSearchNext } from '../InstantSearchNext';
1212

13+
import type { InitialResults } from 'instantsearch.js';
14+
15+
const InstantSearchInitialResults = Symbol.for('InstantSearchInitialResults');
16+
declare global {
17+
interface Window {
18+
[InstantSearchInitialResults]?: InitialResults;
19+
}
20+
}
21+
1322
const mockPathname = jest.fn();
1423
jest.mock('next/navigation', () => ({
1524
...jest.requireActual('next/navigation'),
@@ -31,6 +40,9 @@ describe('rerendering', () => {
3140

3241
beforeEach(() => {
3342
(client.search as jest.Mock).mockClear();
43+
44+
// Simulate initialResults injection
45+
window[InstantSearchInitialResults] = {};
3446
});
3547

3648
it('does not trigger a client-side search by default', async () => {
@@ -50,21 +62,24 @@ describe('rerendering', () => {
5062
});
5163

5264
it('triggers a client-side search on route change', async () => {
53-
mockPathname.mockImplementation(() => '/a');
54-
const { rerender } = render(<Component />);
65+
// Render InstantSearch
66+
const { unmount } = render(<Component />);
5567

68+
// Unmount InstantSearch due to route change
5669
await act(async () => {
5770
await wait(0);
71+
unmount();
72+
await wait(0);
5873
});
5974

60-
mockPathname.mockImplementation(() => '/b');
61-
rerender(<Component />);
75+
// Render InstantSearch on new route
76+
render(<Component />);
6277

6378
await act(async () => {
6479
await wait(0);
6580
});
6681

67-
expect(client.search).not.toHaveBeenCalledTimes(0);
82+
expect(client.search).toHaveBeenCalledTimes(1);
6883
});
6984
});
7085

0 commit comments

Comments
 (0)