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

`useCurrentRefinements` has erroneous behavior in `6.46.0`

joshsmith-watchbox opened this issue · comments

🐛 Current behavior

react-instantsearch-hooks

After upgrading from 6.43.0 to 6.46.0, we are running into an issue where the items value pulled from useCurrentRefinements is causing multiple, additional re-renders. It occurs whenever we use pagination (through useInfiniteHits) to load additional results.

This issue was not occurring in versions prior to 6.46.0.

🔍 Steps to reproduce

In a component utilizing useCurrentRefinements, and utilizing pagination to load additional results, try loading in more results and notice that the items value from useCurrentRefinements is subsequently updated and causes the component to re-render.

Live reproduction

null

💭 Expected behavior

items from useCurrentRefinements should not cause a re-render after paginating additional items.

Package version

6.46.0

Operating system

react-instantsearch-hooks

Browser

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

I'm surprised this is the case as the logic should be equivalent, but this is likely caused by #5696. To try out if that's the issue, can you verify if 6.45.1 does not have the described issue?

Do you have a reproduction of this behaviour so we can verify what's going on?

I am facing same issue with latest

Can you create a reproduction that shows how a render causes an issue @SupriyaPKalghatgi?

Hello @Haroenv 👋

Some context regarding @joshsmith-watchbox's comment: Our scrollToTop() function is being called multiple times when the OnEndReached pagination is successful. It appears that the currentRefinement hook is triggering the useEffect whenever new data is loaded.

  const scrollToTop = () => {
		flatListRef.current?.scrollToOffset({ offset: 0 })
	}

	useEffect(() => {
		scrollToTop() 
	}, [currentRefinements])
	
        const onEndReached = () => {
	   if (!isLastPage) {
	       showMore()
	   }
	}
	
	return (
	<FlatList
		ref={flatListRef}
		data={hits}
	        style={styles.flatListContainer}
		onEndReached={onEndReached}
		ListHeaderComponent={renderHeaderComponent}
		ListFooterComponent={renderFooterComponent}
		renderItem={({ item, index }) => (
				  <Hit hit={item} index={index} />
				)}
		/>
	)

Also happening for me (only on production builds, using NextJS and hosted on Vercel for more context).

Thanks for this report, I now see what's happening. We don't have any guarantees on how many times our hooks render, as just like in other React concepts (think strict mode) components should be resilient against rendering multiple times.

We're thus not guaranteeing that the items reference stays the same when the widget/hook renders multiple times.

Instead of putting an array in the dependency of useEffect, you need to put a primitive (like a string), this actually breaks "rules of hooks" otherwise:

useEffect(() => cleanup, [items.join()])

As this was the only code that was shared, I'll assume that all other commenters fall in the same case. Feel free to comment again and we can have a further look if your use case isn't fixed by this.