algolia / instantsearch

⚑️ Libraries for building performant and instant search and recommend experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.

Home Page:https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

image

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 πŸ’―

image

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 :)