Description
Description
It appears that the
To be more specific about my scenario: I'm using useMenu
of the react-instantsearch-hooks-web
module to create a custom menu. I do this because I want all options to be visible at all times (not depending on what's in the results), have a 'Show all' option and to avoid the behaviour that when I click an item again, it deselects the filter.
I use the isRefined variable to see if I need to check the radio button for that particular filter.
Expected behavior
The isRefined property is properly set when you've refined that facet in your current search.
Current behavior
When picking facets using useMenu the iseRefined value remains false, unless I also pick facets in different filters. The currently refined facet also appears to disappear completely from items
when there are no longer hits in the results based on the other facets in the search. This wasn't previously the case. In 0.30.0 it remained present and set as 'isRefined' because it was part of all refinements.
I've tried setting keepZeroFacets=true, this doesn't help either, it just makes items
turn into an empty array all the time. It also appears the counters for useRefinementList.
Sample code:
Sample code to create a useMenu with radio buttons containing the following items:
- All items
- Items where ContentSubject is set to MUSIC
- Items where ContentSubject is set to DRAMA
- Items where ContentSubject is set to DANCE
The shouldRefine
function serves 2 purposes:
- It checks if the value you're picking to refine, is the one currently already selected, if so it does nothing to avoid deselecting the filter (which is the default behaviour of useMenu. It makes sense if you're not using radio buttons, but we want radio buttons, so that becomes an issue).
- It avoid filtering twice in a row on
""
, as that triggers an error. Callingrefine("")
the first time resets the facet, calling it again causes an error.
function ContentSubjectFilter() {
const { items, refine } = useMenu({
attribute: "contentSubject",
});
const contentSubjects = ["MUSIC", "DANCE", "DRAMA"]; // normally they come from a databse, but I've hard coded them here for the sample
function shouldRefine(items, valueToRefineTo) {
console.log(items); // Here you can see that "isRefined" is no longer being set properly starting with the 2nd option you pick.
let isCurrentlyRefined = !!items.find((item) => item.isRefined == true);
if (isCurrentlyRefined && valueToRefineTo === "") {
return true;
} else if (!isCurrentlyRefined && valueToRefineTo === "") {
return false;
}
let isNewRefineValueSameAsCurrentRefinement = !!items.find((item) => {
return item.isRefined === true && item.value === valueToRefineTo;
});
if (isNewRefineValueSameAsCurrentRefinement) return false;
return true;
}
return (
<ul>
<li>
<label
onClick={(event) => {
event.preventDefault();
if (shouldRefine(items, "")) refine("");
}}
>
<input
checked={!!items.filter((item) => item.isRefined === true)}
name={"contentSubjectRefinement"}
type="radio"
value={""}
defaultChecked
/>
Alles
</label>
</li>
{contentSubjects.map((contentSubject) => {
return (
<li key={contentSubject}>
<label
onClick={(event) => {
event.preventDefault();
if (shouldRefine(items, contentSubject)) refine(contentSubject);
}}
>
<input
checked={
!!items.find(
(item) => item.value === contentSubject && item.isRefined
)
}
name={"contentSubjectRefinement"}
type="radio"
value={contentSubject}
/>
{contentSubject}
</label>
</li>
);
})}
</ul>
);
}