Bug 馃悶
When I add the :sort-by attribute on an ais-refinement-list component, the script make many request to the server instead of one.
When I remove it, the app works fine
Impossible to reproduce on sandbox...
Just one request even with :sort-by attribute
I've tried with or without a ais-configure component (as describe here https://discourse.algolia.com/t/ais-configure-cause-multiple-hit-to-algolia-api-doubling-the-facet-filter/7565), but I've always the same behaivor
"vue": "^2.6.10",
"algoliasearch": "^3.34.0",
"vue-instantsearch": "^2.4.0",
Always try the latest one before opening an issue.
Hi @marekalgoud, it might be that you are passing a new reference everytime, which triggers a rerender and therefore a new request. Can you briefly show us how your declared your component and the value you're passing in the sort-by prop?
Hi @tkrugg,
Thanks for your quick feedback. This is how the component is declared :
<ais-refinement-list
attribute="sizes.rankedNameWithType"
:limit="200"
:sort-by="['name:asc']"
:transform-items="transformItems"
>
<div slot-scope="{items, isShowingMore, isFromSearch, canToggleShowMore, refine, createURL}">
<div
class="c-product-sizer__wrapper"
v-for="(groupItem, groupIndex) in groupSize(items)"
:key="groupIndex"
>
<ul class="c-product-sizer__list">
<li
class="c-product-sizer__item u-1/4"
v-for="item in groupItem"
:key="item.value"
>
<a
:class="{'c-product-sizer-sticker': true, 'c-product-sizer-sticker--selected':item.isRefined}"
:href="createURL(item)"
@click.prevent="refine(item.value)"
>
{{item.label}}
</a>
</li>
</ul>
</div>
</div>
</ais-refinement-list>
@marekalgoud try putting the sort-by attribute in data, and let me know how it goes.
<ais-refinement-list ... :sort-by="sortBy" />
export default {
data() {
return {
sortBy: ['name:asc'],
};
},
};
Hello @tkrugg ,
I've tried it and it works ! Thanks for your help. Could you just explain me why this behaves like this ?
Thanks again !
When a prop is given inline to the component, Vue will call === on its previous value to decide if it fires the relevant watcher. Array references / functions / object are never strict equal to eachother, unless it's the same reference. If you put the value in data, you can compare by reference, and thus no needless watch calls -> requests happen
Ok it's clear for me now :)
Thanks.
You guys are life savers. I struggled with this issue for a day, and the fix outlined above resolved my own issue as well.
My situation was slightly different -- I have multiple custom menu widgets extending the RefinementList component via createWidgetMixin({ connector: connectRefinementList }), and in some cases with a pre-filtered SSR result set, it was possible if a facet refinement in effect for the first refinement list menu to trigger multiple queries in reaction to responsive behavior; wherein the multiple requests must have shared a competing, non-filtered state, as the page would then update to lose all active filters and the entire index would be served.
I think the Vue-InstantSearch documentation for ais-refinement-list could probably use a small note about this pass-by-reference gotcha, since it uses an inline array literal as the example:
<ais-refinement-list
[...]
:sort-by="['isRefined', 'name:asc']"
/>
That's a good point, i'll look into fixing this in the docs