-
Notifications
You must be signed in to change notification settings - Fork 528
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(next-app-router): prevent client-side search when rerendering #6452
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 2ad0eb3:
|
@@ -55,6 +69,10 @@ export function InstantSearchNext< | |||
}; | |||
}, []); | |||
|
|||
useEffect(() => { | |||
window[InstantSearchLastPath] = pathname; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't this also be set if someone has InstantSearch set up with routing for multiple different path names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I get it, are you refering to a situation where there's an InstantSearch implementation in multiple paths and the user navigates from one to the other?
In that case, this is okay as search needs to be triggered.
In any case I'm not fond of having to store this data globally, but I haven't found a good way to track route changes since useRouter
events are not available in app routing. I'm definitely open to ideas around that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking of a use case where with routing someone has for example /search/:category
set up as the path. If you refine the category, won't it also be true here and force an extra search?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change caters to that use case specifically. You can see it in this comment https://github.com/algolia/instantsearch/pull/6452/files#r1863228512.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we had an InstantSearch singleton for React (that's what Apollo does iirc). It would make sure they only use one instance of InstantSearch and we could probably keep track of URLs in there.
|
||
// We only want to trigger a search from a server environment | ||
// or if a Next.js route change has happened on the client | ||
const shouldTriggerSearch = isServer || hasRouteChanged; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InitializePromise
and TriggerSearch
wouldn't do anything on the client.
You don't need to have them to trigger a search on the client, normal CSR with 2 renders kicks in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That means just having isServer
is enough I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This breaks in a dynamic route setting, where a route change caused by Next.js will unmount/remount InstantSearchNext, and not trigger the search.
Adding the check for path change allows <TriggerSearch>
to be mounted and executed as you can see in this recording (the generated sandbox is failing to setup sadly).
I don't exactly understand how it kicks in. Probably Next.js route change performs similarly to router.refresh()
and executes server components?
screenshot-20241129-102623.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah my bad sorry !
Actually I think this solution is nice, we could even choose not to delete initialResults
and it would avoid that flash of no results. Not sure what the condition would look like though, but it can be done later in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And no I think it's because of something with InstantSearch RSC context that makes it not trigger the search even on the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as pathname doesn't seem to change when triggered by InstantSearch, this should work!
Hi, I’ve identified a bug related to this PR: Bug Description:When a user navigates away from a route containing InstantSearch, goes to a route without InstantSearch, and then uses the browser's back button to return, no server-side search is triggered. Additionally, because initialResults are deleted on unmount, no data is displayed. The path is still identified as the InstantSearchLastPath, leading to this issue. Proposed Solution:I suggest modifying the logic to ensure we correctly detect when the route has changed. Here's my suggestion that seem to work for me:
|
Hi @oscarmylla. Deducing the route change from the initial results availability is a better way to cover all use cases. I'll update the behavior in the next version of the package. Thanks for your feedback! |
Summary
This PR updates
<InstantSearchNext>
so it only performs initial search in a server environment.We previously relied on the availability of the initial results (injected in the document), but they are deleted once hydration is complete, which falsely triggers a client-side search when rerendering the component.
FX-3149