`useRefinementList` in Show Less state doesn't respect `transformItems` sort
avremel opened this issue Β· comments
π Current behavior
According to the docs, transformItems
can be used to reorder the refinement values with a custom sort.
When a custom sort is used together with Show More/Show Less functionality, the custom sort isn't applied in the Show Less state. It's only applied in the Show More state.
π Steps to reproduce
- The static sort is defined as
Whirlpool, Sony, Metra
(then the rest). - Observe that in the default state of Show Less, the first three items are incorrectly
Metra, Insignia, Samsung
. - Observe that when selecting Show More, the first three items are correctly
Whirlpool, Sony, Metra
.
Live reproduction
https://codesandbox.io/p/sandbox/next13-4-4-forked-79jevr?file=%2Fcomponents%2FBrands.js%3A11%2C78
π Expected behavior
A custom sort in transformItems
is respected in the Show Less state.
Package version
algoliasearch 4.17.1, react-instantsearch-hooks-web 6.44.0
Operating system
Mac 11.6.5
Browser
Chrome 113.0.5672.126
Code of Conduct
- I agree to follow this project's Code of Conduct
While this is still something I'd like to look into fixing, you can also use "Facet Ordering" (docs: https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/facet-display/js/) to pin certain facets, and not need to use transformItems to sort the items.
We have quite a complex sort - for example: sort brands by most popular per category. It would be difficult to manage with facet ordering.
I believe this is happening because limit gets evaluated before transformItems, which is logical for some use cases, but doesn't seem to match yours, as that causes the items aren't guaranteed to be in place.
However, there's also the sortBy option which does get evaluated before transformItems and seems to match your use case quite well:
useRefinementList({
attribute: "brand",
showMore: true,
limit: 5,
sortBy: useCallback((a, b) => {
if (
CUSTOM_BRAND_SORT[a.escapedValue] !== undefined &&
CUSTOM_BRAND_SORT[b.escapedValue] !== undefined
) {
return (
CUSTOM_BRAND_SORT[a.escapedValue] -
CUSTOM_BRAND_SORT[b.escapedValue]
);
}
if (CUSTOM_BRAND_SORT[a.escapedValue] !== undefined) {
return -1;
}
if (CUSTOM_BRAND_SORT[b.escapedValue] !== undefined) {
return 1;
}
return 0;
}, []),
});
@Haroenv Thanks, didn't realize that sortBy
accepts a function too.
Sandbox links is broken for me.
Sorry, I'm not used to the new sandbox system that automatically makes links private (instead of public).
As sortBy runs first, I think this solves your use case, and the documentation doesn't need to be updated, as the function is already mentioned (not sure how to make it clearer)