algolia / instantsearch

⚑️ Libraries for building performant and instant search and recommend experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.

Home Page:https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error: NextRouter was not mounted.

antoine-lin opened this issue Β· comments

πŸ› Current behavior

Hi, I would like to setup SSR for Algolia using Next.js.
I got a bug with the usage of getServerState from react-instantsearch-hooks-server. I need to use useRouter inside my page but when rendering to string server side the NextRouter context is not mounted leading to this bug:

Screenshot

πŸ” Steps to reproduce

  1. Fork this codesandbox from documentation
  2. Import useRouter and use it in index.tsx
  3. In Next.js 12 (which is the version in use in this sandbox) Next is not crashing but renders null on server when you console.log router. In Next.js 13 the app is crashing.

Live reproduction

https://codesandbox.io/s/bug-reproduction-for-algolia-ssr-with-next-js-bmcpni?file=/pages/index.tsx

πŸ’­ Expected behavior

Initial state from SSR fetch should be resolved without crashing the application.
Having to use react-dom/server inside getServerSideProps seems to not be aligned with how Vercel designed it

Package version

react-instantsearch-hooks-server 6.39.3, react-instantsearch-hooks-web 6.39.1, next 13.1.6, react 18.2.0

Operating system

macOS Ventura 13.2

Browser

Chrome Version 109.0.5414.119 (Build officiel) (arm64)

Code of Conduct

  • I agree to follow this project's Code of Conduct
commented

Hi,

We retrieve the initial InstantSearch state by relying on React's renderToString which renders the component outside of Next.js context. This means there are no possible access to its Hooks, like useRouter(). While it defaulted to null in the previous version, now it throws an Error.

Here are 2 options that have similar outcome (useRouter is null when rendered by renderToString):

  • you can wrap your reference to useRouter in a try {} catch() {} clause
  • you can import useRouter from next/compat/router which fallbacks to the previous behavior

Hi @dhayab thank you for your answer!

I think this solution is too "out of" Next.js. I would like, as much as possible, to rely on Next.js first class exported API.

For those who may face the same issue, I succeed to give correct initialResults to InstantSearchSSRProvider by fetching my indices inside getServerSideProps using algoliasearch SDK.
For the icing on the cake I wrapped it inside @tanstack/react-query to get my dehydrated state I retrieve in my front-end with the benefit of storing results inside react-query cache.

The only downside is that you need to do hacky things to populate initialResults like InstantSearchSSRProvider is waiting for. You may need reduce manipulations.

As you found a solution, we'll close this issue, but we are aware and looking into ways we could expose the widgets without doing a render, or having a guide on how to expose all your necessary contexts in getServerState (Next doesn't really allow it), but that's tracked in other places already.

Thanks for making us further aware

Hi, @antoine-lin

Could you provide an example of how you get the initialResults using algoliasearch inside getServerSideProps, please.