Describe the bug 🐛
Hi,
Thanks for your great module :)
I do have a problem however with how the SSR behaves. I have tried reading all of the issues submitted and guides, examples etc. But I can't figure this out.
It's a bit hard to show what I mean but I managed to reproduce the issue in a fresh CodeSandbox so you can look for yourself.
but these are the main issues:
searchState has no effect IF the RefinementList component is not in the same component with the InstantSearch wrapper. The <Hits> component returns result but if the RefinementList or Menu are in one of the child components, searchState does not work.RefinementList and Menu components DO NOT render on server side if they are not directly in the same component with InstantSearch. They return empty containers on server side. One way to fix this (which is weird) is to have a dummy VirtualRefinementList directly in the same component with InstantSearch, which forces other real RefinementLists to be rendered properly, which in turn causes searchState to take effect correctly (this fixes the first issue as well).To Reproduce 🔍
Steps to reproduce the behavior:
searchState is set to only load PHONES and brands to Apple the result Hits component shows all products on server side (other brands, tablets etc).components/Layout.js. This will make server side render the same thing that the client will render and it also renders the lists correctly.Expected behavior 💭
Server Side rendering should behave the same as client side and take searchState into account.
Environment:
The widgets have to be mounted on the page to be taken into account whether or not the search state is filled. You can imagine them like search parameters for the request. It means that you'll have to use a VirtualMenu in any case to apply the refinement on productType.
In the example the component provided to findResultsState is Layout. But this component does not contain any widgets because they are provided as children so the request is done without any filters. To trigger the correct request you have to provide MyApp to findResultsState. Now that the children does exist and contain widgets the correct request is triggered and the results are rendered. I've updated the example with the correct resolution.
@samouss Thanks! Oh I didn't know I could recursively pass the MyApp to findResultsState. I'll try that locally and will close this if it's working. However it would be so nice if there was a more concrete and up-to-date documentation.
Yes, we'll simplify a bit the SSR API in the next months. We'll take this opportunity to revamp the doc on the SSR. Thanks for the feedback!
@samouss I just applied the changes to my app and it works beautifully :) Thank you very much. before closing this issue however, one last question: Is there a chance to make Algolia NOT send a new network request on client side since the resultsState is already populated on first load?
It's not currently possible, but you're completely right it's possible to avoid it. We'll integrate this change in the next iteration of the SSR API.
Thank you very much :) I’ll be waiting for those features ✋️
Is this documented anywhere? Just spent an hour chasing this bug :(
Further: I understand widgets need to be collected before a complete request can be sent, but I am passing a searchState directly into <InstantSearch> so it would make sense these values be used even if no widget overrides them
We indeed have not yet found a good place for the server side rendering docs to live. I'll reopen this so we can keep an eye on the issue, sorry @cloakedninjas for your experience
@cloakedninjas We touch this subject a bit in the last section of the SSR guide but we could indeed emphasize this more.
React InstantSearch is a declarative API that programmatically builds an Algolia query. Based on every widget used, and their own options, we compute a set of parameters that should be sent to Algolia.
Most helpful comment
The widgets have to be mounted on the page to be taken into account whether or not the search state is filled. You can imagine them like search parameters for the request. It means that you'll have to use a
VirtualMenuin any case to apply the refinement onproductType.In the example the component provided to
findResultsStateisLayout. But this component does not contain any widgets because they are provided aschildrenso the request is done without any filters. To trigger the correct request you have to provideMyApptofindResultsState. Now that thechildrendoes exist and contain widgets the correct request is triggered and the results are rendered. I've updated the example with the correct resolution.