`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.