react-instantsearch icon indicating copy to clipboard operation
react-instantsearch copied to clipboard

Re-render of custom hits component when updating shared state is slow

Open stianmartinsen opened this issue 4 years ago • 7 comments

Describe the bug 🐛

I'm building an app using react-instantsearch where I'm going to show a list of hits and a map with each hit represented by a marker. Pretty standard stuff.

I want the corresponding marker to be highlighted when I hover an item in the list, and vice versa. For this, I'm storing the currently hovered ID in a shared state using the useState hook, and pass along the value and the setter to the custom hit component. When hovering the hit, I update the state with the hit's ID.

I notice that it takes a while for the component to re-render after updating the state. You can see this in the following code sandbox:

To Reproduce 🔍

Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/s/sweet-driscoll-hvk9q
  2. Hover any search result in the custom Hits component
  3. See that it takes a while for the "HOVERING" text to appear in the Hit

Expected behavior 💭

The text "HOVERING" should be visible with no delay when hovering a Hit.

Any tips to how I can remove this delay? :)

stianmartinsen avatar Jun 09 '20 13:06 stianmartinsen

Is there a reason you need to store the state of hovering all the way from hits back to outside of InstantSearch? If you for example move the state into hits, and thus prevent the whole tree from rerendering, this issue doesn't seem to happen. https://codesandbox.io/s/cocky-firefly-1jmzw?file=/src/App.js

Could you explain the use case for hoisting the rerender to that level?

Haroenv avatar Jun 09 '20 15:06 Haroenv

Yes, I want to display the hovered item differently in another widget, in my case a custom geosearch. And I also want to render the Hit component differently when I hover the same hit in the geosearch. So I think I need the hovered state to live in the parent component.

stianmartinsen avatar Jun 09 '20 17:06 stianmartinsen

In which case you can move the state to this level:

<InstantSearch>
  <Content>
</InstantSearch>

and have the state live in Content, or another wrapper of just geo & hits

Haroenv avatar Jun 10 '20 09:06 Haroenv

Thanks! That seems to make it a bit snappier, but it's still not instant. See a new example here: https://codesandbox.io/s/dreamy-breeze-tytbn

I wonder how Algolia makes this example so fast, I can't see what I'm doing differently: https://community.algolia.com/instantsearch.js/v2/dev-novel/?selectedStory=GeoSearch.with%20Hits%20communication%20%28custom%29

stianmartinsen avatar Jun 10 '20 09:06 stianmartinsen

that example doesn't use React, so doesn't have the same limitations wrt state

Haroenv avatar Jun 10 '20 09:06 Haroenv

Ah, of course. I thought I was viewing the React storybook, but I see now that the React version of this story is a bit more sluggish than the vanilla JS one: https://react-instantsearch.netlify.app/storybook/?path=/story/geosearch--with-hits-communication-custom

I will fall back to using regular event listeners and toggling class names for now, but if anyone has any tips on how to make my code example more performant while using state, I'll be really happy :)

stianmartinsen avatar Jun 10 '20 10:06 stianmartinsen

@stianmartinsen Just a drive by idea, not thought through, but maybe you could use React context to avoid passing your selected item deeply into the hierarchy? I'd be interested to hear if that solves it.

websocket98765 avatar Jun 18 '20 18:06 websocket98765

Hi! We're doing a round of cleanup before migrating this repository to the new InstantSearch monorepo. This issue seems not to have generated much activity lately, so we're going to close it, feel free to reopen if needed.

dhayab avatar Dec 22 '22 09:12 dhayab