Hi all,
be patient with the n00b question but I’m having a hard time with my application built with Next.Js.
- UI library: React InstantSearch Hooks
- Framework: Next.Js
As the search is the core of the app I set up the navbar and megamenu item to link directly to the filtered InstantSearch page.
i.e: “Item1” from the menu link to http://localhost:3000/explore?regions=something
If I input the link in my browser it works but when I am on the InstantSearch (without SSR) page and click on the menu item nothing happens.
You can find the working example here: Explore Wines - Wine Match
I gave a try to the routing package for React InstantSearch Hooks that is compatible with Next.js routing: react-instantsearch-hooks-router-nextjs
.
The issue seems fixed but I can’t figure out how to implement my previous custom router developed (i.e. SEO friendly URLs) to this new package.
Following the official GitHub page (without SSR):
<InstantSearch
searchClient={searchClient}
indexName="instant_search"
routing={{
router: createInstantSearchRouterNext({
singletonRouter,
serverUrl: url,
routerOptions: {
createURL: /* ... */,
parseURL: /* ... */,
},
}),
// if you are using a custom `stateMapping` you can still pass it :
stateMapping: /* ... */,
}}
>
Here is an example of my previous code without react-instantsearch-hooks-router-nextjs:
const router = historyRouter<RouteState>({
createURL({ qsModule, routeState, location }): string {
const { protocol, hostname, port = "", pathname, hash } = location
const portWithPrefix = port === "" ? "" : `:${port}`
const urlParts = location.href.match(/^(.*?)\/explore/)
const baseUrl =
(urlParts && urlParts[0]) ||
`${protocol}//${hostname}${portWithPrefix}${pathname}`
const queryParameters: Partial<RouteState> = {}
if (routeState.query) {
queryParameters.query = encodeURIComponent(routeState.query)
}
if ( routeState.regions ) {
queryParameters.regions = routeState.regions.map(encodeURIComponent)
}
const queryString = qsModule.stringify(queryParameters, {
addQueryPrefix: true,
arrayFormat: "repeat",
})
return `${baseUrl}${queryString}${hash}`
},
parseURL({ qsModule, location }): RouteState {
const queryParameters = qsModule.parse(location.search.slice(1))
const { query = "", regions = [] } = queryParameters
const allRegions = (
Array.isArray(regions) ? regions : [regions].filter(Boolean)
) as string[]
return {
query: decodeURIComponent(query as string),
regions: allRegions.map(decodeURIComponent),
}
},
})
const getStateMapping = ({ indexName }) => ({
stateToRoute(uiState: UiState): RouteState {
const indexUiState = uiState[indexName]
return {
query: indexUiState.query,
regions: indexUiState.refinementList && indexUiState.refinementList.region,
}
},
routeToState(routeState: RouteState): UiState {
const refinementList: { [key: string]: string[] } = {}
if (routeState.regions) { refinementList.region = routeState.regions}
return {
[indexName]: {
query: routeState.query,
refinementList,
},
}
},
})
const getRouting = (indexName: string) => ({
router,
stateMapping: getStateMapping({ indexName }),
})
export default getRouting
How can I migrate the previous code to the new package?
Thank you in advance