Closed nachoadjust closed 1 year ago
When you are relying on custom parameters for the backend search, you'll need to somehow also apply those to the frontend. To avoid this mismatch we've set it so that ui state is the source of truth. This indeed means that asynchronously setting an initial state wasn't what we had in mind.
Do you have a live sample of your previous implementation somewhere? I can understand the individual parts of the code, but not fully sure how it all works together, especially both using asyncData & serverPrefetch
Hello @Haroenv, thank you very much for jumping in!
Here is the sandbox you requested.
The page should load some resources of our site (ebooks).
It should do it for the English version only. But when the page loads you will probably see a "glitch", where:
(If the error doesn't trigger initially try reloading codesanbox's browser).
I believe this is because the searchParameters
are not being passed to the Algolia instance in this new version of vue-instantsearch (v4)
in v2 we would just do this passing inside asyncData
:
async asyncData (context) {
try {
const story = await api.getStoryFromCMS(context)
const searchParameters = {
hitsPerPage: 12,
filters: `(type:Ebook) AND locale:${context.app.i18n.locale} AND NOT hideInSearch:true`,
disjunctiveFacets: ["topics"]
}
let instantSearchState = await instantsearch.findResultsState(searchParameters)
instantSearchState = instantsearch.getState()
return {
story,
instantSearchState,
searchParameters,
refinementParameters: searchParameters.disjunctiveFacets,
query: "",
}
} catch (error) {
return api.handleErrors(context, error)
}
}
What you could do is add a virtual refinement list for locale
, and use context.app.i18n.locale
in the stateMapping to enable the right refinement, so it's not required to use filters directly
Hello @Haroenv. Could you provide an example of how to apply what you described that fits the code I provided? Because I am having trouble understanding how to apply what you mentioned and I have not found any docs for virtualRefinementList for Vue, only for React.
I see that there seems to be a mapping between connectRefinementList
to ais-refinements-list
(see link)
I assume this means that ais-refinements-list
is algolia-Vue's connectRefinementList
?
Thank you in advance!
Side Note:
I was checking the codebase for algolia v2 specifically for findResultsState
to try and understand more about the issue:
search.findResultsState = params => {
search.helper = algoliaHelper(
searchClient,
indexName,
_objectSpread({}, params, { // <<<<<<< HERE
// parameters set by default
highlightPreTag: '__ais-highlight__',
highlightPostTag: '__/ais-highlight__',
})
);
return search.helper.searchOnce().then(({ content: lastResults }) => {
// The search instance needs to act as if this was a regular `search`
// but return a promise, since that is the interface of `asyncData`
search.helper.lastResults = lastResults;
});
}
This approach allowed us to request+filter the data to Algolia and get the response we needed already on Server side.
I see the approach of passing searchParameters
has been removed since v3, but I cannot find any info explaining how get the same result as in v2 using the ways of v3.
Are there any docs that might help me ?
Thanks again!
Sorry, there's no docs as we considered this v2 behaviour rather a bug (state isn't in sync with UI) than a feature. I'm not fully sure how to create your use case though, so would have to consider how to pass state correctly. A virtual refinementList is indeed not documented for vue, as you can use <ais-configure />
or <ais-refinement-list hidden />
@Haroenv thanks for the quick reply.
I was not aware of this information you shared. Our implementation of Algolia was done by someone else before me and I lack documentation.
All approaches I have tried so far have failed to get the correct initial data response on the server side. It only works on client side.
This is noticeable in the sandbox I provided. There you can see that when the page loads it renders some cards, and 3-4 seconds later the data refreshes and the page loads the correct cards.
This is also an issue for the static generation of our site, as the .html files get created with the wrong data in them.
I will keep on reading to see if I find a fix, but unless I can provide filters when I make the SSR data request to algolia, I doubt I can get this to work.
If you can provide any useful documentation to point me in the right direction that will be greatly appreciated.
Either something simple was wrong with my example, or something else was happening, but in theory this should work: https://codesandbox.io/s/test-algolia4-forked-xmbj5?file=/pages/index.vue (moving the parameters inside the rendered component, so that the parameters can be taken in account
@Haroenv thank you for the code example, however I see the issue still happening. It does take the filters, but only on client side, but on server side the data the server sees is the one without the filters. I have recorded a video to try to explain the issue completely, so that I don't bombard you so much with messages. Maybe it helps? Thanks again for the effort!
Sorry for being unclear, but I indeed also see the issue, but not what the solution is
From my understanding the only way to achieve this would be to allow findResultsState()
to accept search parameters. (But I do not know what disadvantages that might have on other parts of algolia's code.)
That wouldn't be possible, it doesn't deal directly with search parameters, and also there isn't really a use case for sending a different request on the server than on the client. What I think is likely going wrong in the example I made is that on the server the props/parameters aren't correctly forwarded (maybe related to cloneComponent?)
What I think is likely going wrong in the example I made is that on the server the props/parameters aren't correctly forwarded (maybe related to cloneComponent?)
Yes, that is correct. I thought findResultsState
was in charged of receiving them, that's why I suggested it.
I am not aware of cloneComponent
and how to use. Is it part of Algolia's implementation?
$cloneComponent
is a function passed to createServerRootMixin
, which copies the "component" to be able to render it and get all child components. The default implementation is
I haven't tested this case extensively yet, so I'm not sure, but it's possible that one of the ways nuxt is injecting the locale isn't copied by the cloneComponent
I don't think we'll make any changes to how this functions to enable the previous design, as it wasn't designed for that purpose. Best would be to use the earlier suggested initial ui state or routing.
Issue
We are trying to migrate our Algolia implementation from v2 to v4.
We use Nuxt and we have implemented the exampled explained here which "works".
However we are not being able to find out how to provide the search parameters to filter the data for SSR in v4.
This results in our page loading the wrong information on SSR and updating it on the client:
How we are currently doing it (using v2):
In v2 we do not have the issue described as the correct data already comes included in the page. We use the
asyncData
hook to request our data from the CMS, and to create the Algolia state.How we are trying to implement it using v4:
The template part looks like this in both cases:
In v2 we can easily pass the parameters to define the state, and provide the result to the client for the hydration:
How can the same be achieved in v4?