Query parameters disappearing after submitting the search box

Hello,

I am using Next.js with React InstantSearch Hooks , and I have encountered an issue with the search query disappearing from the URL after submitting the search box when transitioning from one page to another. This problem does not occur if I perform a search on the result page itself.

For example, when I press enter on the search box on ‘http://localhost:3000’, the home page, I am first redirected to ‘http://localhost:3000/results?query=edp’, but then the URL immediately changes to ‘http://localhost:3000/results’, causing the search query to disappear and the ui state to reset, the searchbox is empty. No 301 occur in the network tab.

Here is the routing configuration from my current _app.js implementation:

import { createInstantSearchRouterNext } from 'react-instantsearch-hooks-router-nextjs';
import { InstantSearch } from 'react-instantsearch-hooks-web';
import { searchClient } from '../lib/algolia/searchClient';
import { ClerkProvider } from "@clerk/nextjs";
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import { history } from 'instantsearch.js/es/lib/routers';

// other imports

function MyApp({ Component, pageProps, serverState, serverUrl }) {

  const router = useRouter()
  const { query } = router
  const routing = {
    router: history({
      windowTitle({ query }) {
        const queryTitle = query ? `Resultats pour "${query}"` : 'Recherche';

        return queryTitle;
      },

      createURL({ qsModule, location, routeState }) {
        const { origin, pathname, hash } = location;
        const indexState = routeState[process.env.NEXT_PUBLIC_ALGOLIA_DEALS_INDEX_NAME] || {};
        const queryString = qsModule.stringify(routeState);
  
        if (!indexState.query) {
          return `${origin}${pathname}${hash}`;
        }
        return `${origin}${pathname}?${queryString}${hash}`;
      },

      parseURL({ qsModule, location }) {
        const { query = '', brands = [] } = qsModule.parse(
          location.search.slice(1)
        );
        // `qs` does not return an array when there's a single value.
        const allBrands = Array.isArray(brands)
          ? brands
          : [brands].filter(Boolean);

        return {
          query: decodeURIComponent(query),
          brands: allBrands.map(decodeURIComponent),
        };
      },
    }),

    stateMapping: {
      stateToRoute(uiState) {
        const indexUiState = uiState[process.env.NEXT_PUBLIC_ALGOLIA_DEALS_INDEX_NAME]|| {};

        return {
          query: indexUiState.query,
          ...query
        };
      },

      routeToState(routeState) {
        return {
          [process.env.NEXT_PUBLIC_ALGOLIA_DEALS_INDEX_NAME]:  {
            query: routeState.query,
            ...query
          },
        };
      },
    },
  };

// ...

  return(
      <ClerkProvider
        {...pageProps}
        appearance={{
          elements: {
            socialButtonsBlockButton__google: {
              display: isFacebook ? "none" : "flex",
            },
          },
        }}
        localization={defaultResource} 
      >
        <InstantSearch
          searchClient={searchClient()}
          indexName={process.env.NEXT_PUBLIC_ALGOLIA_DEALS_INDEX_NAME}
          routing={routing}
        >
          <Component {...pageProps} />
        </InstantSearch>
      </ClerkProvider>
  )
}

export default MyApp

The results page is pretty basic:

// pages/results/index.js
export default function Index() {

  const { user } = useUser();
  const router = useRouter();
  const { query } = router;

  return (
    // ....
  )
}
```

Do you have any idea to solve this problem and maintain the uistate with the search query in the result page?

Thank you for you help.

2 Likes

I have the exact same use case and exact same issue. I’d love to hear if anyone has figured this out.

2 Likes

same issue, I’m using the Nextjs router package createInstantSearchRouterNext

<InstantSearch
  searchClient={searchClient}
  indexName={searchIndex}
  routing={{
    router: createInstantSearchRouterNext({
      singletonRouter,
    }),
  }}
    <SearchBox />
</InstantSearch>

I get this console warning


[InstantSearch.js]: The UI state for the index "themes" is not consistent with the widgets mounted.

This can happen when the UI state is specified via `initialUiState`, `routing` or `setUiState` but that the widgets responsible for this state were not added. This results in those query parameters not being sent to the API.

To fully reflect the state, some widgets need to be added to the index "themes":

- `query` needs one of these widgets: "searchBox", "autocomplete", "voiceSearch"

If you do not wish to display widgets but still want to support their search parameters, you can mount "virtual widgets" that don't render anything:

const virtualSearchBox = connectSearchBox(() => null);

search.addWidgets([
  virtualSearchBox({ /* ... */ })
]);

If you're using custom widgets that do set these query parameters, we recommend using connectors instead.

See https://www.algolia.com/doc/guides/building-search-ui/widgets/customize-an-existing-widget/js/#customize-the-complete-ui-of-the-widgets
1 Like

Hi guys ,

@charles @dev28 @rob7
please refer to this you can find the solution or else you post your code in the stackblitz. so that i can fix it.

examples

for basic

  <InstantSearch
      searchClient={searchClient}
      indexName="instant_search"
      routing={true}
    >
      {/* ... */}
    </InstantSearch>

how to create url this helps you.

changing the state of the URL this can help you.

Implemented in Angular by me :

Has anyone been able to make this work with NextJS?

I am also having the issue that each new query input will set the URL and then reset it straight away.

Here is my code:

      <InstantSearch
        searchClient={searchClient}
        indexName={index}
        insights={true}
        routing={{
          router: createInstantSearchRouterNext({
            singletonRouter
          }),
        }}
      >
        <CustomSearchBar namespace={'actor'} />
        <SearchResult extended={extended} />
      </InstantSearch>
1 Like

Your “solution” is written in angular when everyone here is asking about the nextjs implementation with createInstantSearchRouterNext. Can you give us a solution with that instead?

I’m facing a similar issue. I’m using Next 13.2.1 with React 18.2.0 and createInstantSearchRouterNext with SSR, and if I access a URL with ?q=someSearchString, the results show up, but then the params disappear, and the page refreshes.

I have looked for possible middlewares that could be rewriting or redirecting the page on param change, but that did not help.

I also have to use the next/compat/router in conjunction with the default router, so I tried removing that usage and leaving the default router only, to no avail.

I have tried other reactors, such as removing the Layout component, which also contains the SearchBox, but that did not help.

I have yet to create a reproducible sample for others to test, but that takes some time.

3 Likes