Bug 馃悶
I am trying to implement the nuxt + ssr + routing examples from the docs: https://www.algolia.com/doc/guides/building-search-ui/going-further/routing-urls/vue/#combining-with-vue-router
I recoreded a gif so you can reproduce the steps yourself:

This sandbox (serene-leftpad-jp7gb) contains basically just code from the docs
https://codesandbox.io/s/serene-leftpad-jp7gb
Route only pushed once
No
I don't know
3.2.0
Always try the latest one before opening an issue.
Quick fix for this problem, just check if the query truly changed. Not pretty but gets the job done.
function nuxtRouter(vueRouter) {
return {
read() {
[...]
},
write(routeState) {
if (this.createURL(routeState) !== this.createURL(this.read())) {
vueRouter.push({
query: {
...routeState,
},
})
}
},
createURL(routeState) {
return vueRouter.resolve({
query: routeState,
}).href
},
[...]
}
}
export { nuxtRouter }
Additionally to that I have another issue which I can't replicate in a sandbox but it is real. If someone has an idea what could go wrong here please let me know:
Scenario:
State: brand=ABC&category=dog
The original SSR state is shown meaning: brand=ABC
No matter what I select (even unselecting everything) the original SSR state is shown.
If I visit the search page through example.com/ -> [navigate to] -> example.com/search. Everything works as expected.
After 2 days of debugging I found this "solution" -> nuke the algoliaState after it was used in beforeMount:
this.$nuxt.context.nuxtState.algoliaState = undefined
window.__NUXT__.algoliaState = undefined
thanks for passing this workaround, it's indeed correct, and so is the workaround to your second problem. I'll update the documentation to include these points!
Heya, had to test this to see if it was a nuxt problem or a vue storefront problem: made a minimal repo: https://github.com/ed42311/algolia-nuxt-routes
To clarify: it seems that that the problem I'm seeing is with VSF, but I thought this might be useful
The documentation has not been updated yet, but a fully correct router that works with back button in vue should be:
function nuxtRouter(vueRouter) {
let writeTimer = null;
let removeAfterEachListener = null;
let popStateListener = null;
return {
read() {
return vueRouter.currentRoute.query;
},
write(routeState) {
// Only push a new entry if the URL changed (avoid duplicated entries in the history)
if (this.createURL(routeState) === this.createURL(this.read())) {
return;
}
if (writeTimer) clearTimeout(writeTimer);
writeTimer = setTimeout(
() =>
vueRouter.push({
query: routeState,
}),
400
);
},
createURL(routeState) {
return vueRouter.resolve({
query: routeState,
}).href;
},
onUpdate(cb) {
removeAfterEachListener = vueRouter.afterEach((to, from) => {
console.log('haaah', to.query)
cb(to.query);
});
if (typeof window === "undefined") return;
popStateListener = () => {
cb(this.read());
};
window.addEventListener("popstate", this._onPopState);
},
dispose() {
if (writeTimer) clearTimeout(writeTimer);
if (removeAfterEachListener) removeAfterEachListener();
if (typeof window === "undefined") return;
window.removeEventListener("popstate", popStateListener);
},
};
}
@Haroenv this solution lead to a infinit route change on my project.. so every 400ms i see the url without any params that it shows them and removes them again..
this code seems to work for my project at least:
import qs from 'qs'
function nuxtRouter(vueRouter) {
const routeWritten = null
let popStateListener = null
return {
read() {
return qs.parse(vueRouter.currentRoute.query)
},
write(routeState) {
// Only push a new entry if the URL changed (avoid duplicated entries in the history)
if (this.createURL(routeState) === this.createURL(this.read())) {
return
}
if (!routeWritten) {
setTimeout(
() =>
vueRouter.push({
query: routeState
}),
400
)
}
},
createURL(routeState) {
return vueRouter.resolve({
query: routeState
}).href
},
onUpdate(cb) {
if (typeof window === 'undefined') return
popStateListener = () => {
cb(this.read())
}
window.addEventListener('popstate', this._onPopState)
},
dispose() {
if (typeof window === 'undefined') return
window.removeEventListener('popstate', popStateListener)
}
}
}
just found a small bug..
read() {
return vueRouter.currentRoute.query
},
is not eqal:
read() {
return qs.parse(vueRouter.currentRoute.query)
},
so if i use qs.parse in read() it also works on client side navigation with query params.
using qs is best done in the vue router configuration itself, and not in the router here: https://www.algolia.com/doc/guides/building-search-ui/going-further/routing-urls/vue/#combining-with-vue-router
yes.. but in my case it was the only way i could fix it as the result of read() was on SSR a different one as on the client side. but as suggested i also use it in my nuxt config as described.
found this awhile back: https://code.luasoftware.com/tutorials/algolia/setup-algolia-instantsearch-on-nuxt-with-query-url/
seems to resolve the loading error, probably because of the callback timing?
also lets you clean up the url
something else i discoverd this morning:
if you keep some views alive in nuxt the solution is not working.
You need to exclude the component than includes the Algolia Components from the keep-alive prop.