algolia / instantsearch-ios

⚡️ A library of widgets and helpers to build instant-search applications on iOS.
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/ios/
Apache License 2.0
591 stars 55 forks source link

HitsObservableController not clearing out old results after applying filter #302

Closed jonathanjr3 closed 2 months ago

jonathanjr3 commented 6 months ago

Describe the bug 🐛 The hits property in HitsObservableController which comes with InstantSearchSwiftUI library is not updating results properly, results from previous fetch are also included in the list. I've observed that this only happens when user scrolls past the offset limit set in the HitsInteractor infinite scrolling parameter.

For example: Let's assume the total number of hits without any filter applied is 25. Algolia SDK fetches 20 hits by default on first load of the page and I've also set infiniteScrolling to on with 10 as offset like this:

activityHitsConnector = .init(searcher: activitySearcher,
                                      interactor: .init(infiniteScrolling: .on(withOffset: 10), showItemsOnEmptyQuery: true),
                                      controller: activityHitsController)

Scrolling past the first 10 hits loads the remaining 5 and updates the hits property in HitsObservableController as expected. The total result count of the hits property is 25 now.

If I apply a filter with a facet which has just 1 value for example, the relevant result is at the top of the hits list but the other 5 values which were fetched previously are also included in the list. So the list is showing 6 results instead of 1.

This does not happen if we don't scroll past the offset limit (i.e 10), the hits list contains only the expected result (1 in this case) if we don't scroll past the limit.

To simplify this:

(infiniteScrolling offset set as 5)

  1. Initial hits list (assuming it loads 5 by default) : A, B, C, D, E
  2. Scroll past 'E', SDK loads the next 5 onto the list: A, B, C, D, E, F, G, H, I, J
  3. Apply a filter which should show only 'B' for example (facet with just one value), now the list is: B, F, G, H, I, J

I'm applying filters using toggle(_ facet: Facet, for attribute: Attribute) function in DynamicFacetListObservableController and disjunctive groups in FilterState using filterState[or: attribute].addAll()

To Reproduce 🔍 Steps to reproduce the behavior:

  1. Connect HitsSearcher, HitsInteractor and HitsObservableController objects using HitsConnector
  2. Set infiniteScrolling to on with offset as 10 in HitsInteractor object
  3. Display hits list using HitsList view provided by InstantSearchSwiftUI
  4. Scroll past 10 items and verify if the next set of results are loaded in the list
  5. Apply a filter with a facet value lesser than the current count of the list (1 for example)
  6. hits property will have the relevant result as the first element, including the ones fetched previously.

Expected behavior 💭 hits list in HitsObservableController should only have the relevant result(s)

Screenshots 🖥 Initial list without any filters applied, without scrolling, includes all results: Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 27 10

Applying a filter with a facet which has 1 value (Beachtennis): Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 27 29

Works as expected, showing 1 result: Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 27 33

Remove that filter, scroll past 10 items and apply the same filter: Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 28 38

Here you could see the relevant result is at the top but the results which were fetched before due to scrolling below are also included

Screen recording:

https://github.com/algolia/instantsearch-ios/assets/123464885/1471d08e-f27d-4fa2-af0c-0b9a31d0628a

Side note: We're using StatsTextObservableController to show the number of results in the segmented picker below the search bar

Environment:

Additional context Please let me know if you need more details.

jonathanjr3 commented 4 months ago

@VladislavFitz adding another observation here, this is happening with a custom scrollview and SwiftUI's native List too. Please let me know if there are any updates and if you need more details on this, thank you.

jonathanjr3 commented 2 months ago

Reached out to algolia support team and the solution they provided has fixed this issue, closing this issue henceforth.