Vue-instantsearch: Multiple calls to the api when adding :sort-by attribute on ais-refinement-list component

Created on 13 Sep 2019  路  8Comments  路  Source: algolia/vue-instantsearch

Bug 馃悶

What is the current behavior?

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

Make a sandbox with the current behavior

Impossible to reproduce on sandbox...

What is the expected behavior?

Just one request even with :sort-by attribute

Does this happen only in specific situations ?

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

What is the proposed solution?

What is the version you are using?

"vue": "^2.6.10",
"algoliasearch": "^3.34.0",
"vue-instantsearch": "^2.4.0",

Always try the latest one before opening an issue.

All 8 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vasilestefirta picture vasilestefirta  路  4Comments

bobylito picture bobylito  路  4Comments

matthewmnewman picture matthewmnewman  路  6Comments

michaelchiche picture michaelchiche  路  4Comments

fi0 picture fi0  路  3Comments