router UiState does not receive `configure.filters` values when set with `setIndexUiState`.
jsancho opened this issue Β· comments
π Current behavior
For reference, I have a proof of concept where this behaviour can be seen
https://codesandbox.io/p/github/jsancho/algolia-routing/main
This sample project has a few InstantSearch widgets with custom UI that can be hidden when the toggle at the top right is used.
The 2 main objectives are
- to keep the query the same when the filters are hidden from view
- to save the query state to the url, so that users can share links to specific data views.
So far this is working with the SortBy
and SearchBox
widgets, i.e. the data is kept in sync with the url regardless of the widgets being visible.
The issue can be seen when using the time range dropdowns above the sortyBy.
They are working as far as querying data goes.
If you change the dropdown from "today" to other values, you will see how the data is filtered accordingly, but that the options selected are not synced with the url.
The simple router in the instantsearch repo does explicitly remove the configure
values.
So I have modified that exclude logic, but the UiState is still received with an empty configure
object.
https://codesandbox.io/p/github/jsancho/algolia-routing/main?file=%2Fsrc%2Flib%2Fsimple.ts
My expectation was to be able to serialise the filters
to the url just like I do with the sortBy after a setIndexUiState.
Is this behaviour supported?
Also, I am a bit unsure about how to use the useConfigure
hook, as there aren't any live examples in the docs.
As you can see here I'm passing an empty object by default.
https://codesandbox.io/p/github/jsancho/algolia-routing/main?file=%2Fsrc%2Fcomponents%2Ffilters%2Fvirtual%2FVirtualDateFilters.tsx
Similarly to the case with the router, indexUiState.configure.filters
is always undefined on this virtual component.
This could be related to the issue above or I could also be misunderstanding how to setup these widgets altogether.
thanks very much for the help
π Steps to reproduce
- Open the sandbox
- Change the values on the dropdown that has the "today" value.
- the data is filtered, but the filters are not saved to the URL
Live reproduction
https://codesandbox.io/p/github/jsancho/algolia-routing/main
π Expected behavior
I should be able to use virtual widgets to configure the "filters" that are passed to Algolia.
Package version
"react-instantsearch-hooks-web": "^6.38.3", algoliasearch": "^4.14.3", "instantsearch.js": "^4.49.4"
Operating system
Windows 11
Browser
Chrome (latest)
Code of Conduct
- I agree to follow this project's Code of Conduct
Hi @jsancho,
Are you using setIndexUiState
only to address the fact that the state gets cleared when FiltersSideBar
is unmounted ?
There is a specific guide for persisting state when hiding widgets : https://www.algolia.com/doc/guides/building-search-ui/widgets/show-and-hide-widgets/react-hooks/
I checked your code, and in your case you can hide your FiltersSideBar
with CSS display: none;
rather than unmounting it. It would be much simpler to handle, you wouldn't need virtual widgets anymore either.
So instead of doing {showFilters && <FiltersSideBar />
you could do <FilterSideBar show={showFilters} />
in which you would do something like <aside style={{ display: show ? "block" : "none" }}>
or with a class if you want.
If you absolutely have to unmount it, you can follow what's in the "Persist the state on unmount" section. You don't need to handle it on each widget. In this case I think you could go back to using refine
functions and only call setUiState
once to persist when unmounting FiltersSideBar
.
Now as for the second issue, you can use the Configure
component directly in DateFilters
:
export const DateFilters = ({ index }: IProps) => {
const [filters, setFilters] = useState<IDateFilters>({
dateField: defaultDateField,
timeRange: getTimeRangeForPeriod(defaultTimePeriod)
});
const onChangeDateField = (dateField: string) => {
setFilters(prev => ({ ...prev, dateField }));
};
const onChangeTimePeriod = (timePeriod: TimePeriod) => {
const timeRange = getTimeRangeForPeriod(timePeriod);
setFilters(prev => ({ ...prev, timeRange }));
};
const filter = `${filters.dateField}TimeStamp: ${filters.timeRange}`;
return (
<>
<DateFieldDropdown
index={index}
defaultValue={defaultDateField}
onChangeDateField={onChangeDateField}
/>
<TimePeriodDropDown
defaultValue={defaultTimePeriod}
onChangeTimePeriod={onChangeTimePeriod}
/>
<Configure filters={filter} />
</>
);
};
With this I can see the URL gets updated !
Hope this helps !
wow π€― !
This approach is so much easier than using virtual components indeed.
I've managed to refactor all the code in the sandbox to work without them and this is an absolute treat, it's so much clearer.
I was receiving plenty of instantsearch warnings in the console that prompted me to use virtual widgets, and that's what essentially lead me down that road.
Matter of fact is that I still get some of the warnings. but only for the refinement widgets when I refresh the page.
Despite that, it's all working as expected, so you can consider this issue closed from my end.
Only sharing this as an FYI in case somebody faces this issue as well.
thanks so much for such a clear and thoughtful response π―
Hi @jsancho,
Glad it works now !
As for the warning, this is because you're using DynamicWidgets
which adds the refinement list a bit later so that's why you see this warning. It will not show in code built for production, so you can safely ignore it.
As for the warning, this is because you're using
DynamicWidgets
which adds the refinement list a bit later so that's why you see this warning. It will not show in code built for production, so you can safely ignore it.
That makes sense, thanks for that :)