algolia / vue-instantsearch

👀 Algolia components for building search UIs with Vue.js
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/vue
MIT License
854 stars 157 forks source link

AisInstantSearchSsr make child component life circle trigger twice #1122

Closed sonnd08 closed 2 years ago

sonnd08 commented 2 years ago

Bug 🐞

What is the current behavior?

Every child component inside AisInstantSearchSsr will be rerendered twice. In my case, there are several API calls in fetch function and they are all being called twice I think it is ok because it run fine in local but then everything becomes serious when Cloudflare always return 502 error on these pages (In server logs, no crash). I'm going to switch back to client side AIS while checking further.

Note: We use Cloudflare as a DNS service

Make a sandbox with the current behavior

https://codesandbox.io/s/dawn-night-v4phem?file=/components/Tutorial.vue

What is the expected behavior?

Fetch should be called only one or Cloudflare not return 502 on these pages

Does this happen only in specific situations?

Always happens

What is the proposed solution?

Some changes with this step?

Original function at vue-instantsearch/src/util/createServerRootMixin.js
...
.then(() => renderToString(app))

What is the version you are using?

    "nuxt": "2.14.6",
    "vue": "^2.6.14",
    "vue-instantsearch": "^4.3.3",
    "algoliasearch": "^4.13.0",
Haroenv commented 2 years ago

We must render a "second" time to get access to which widgets are mounted so the search request can happen. What you can do however is:

  1. make sure calling render twice isn't problematic
  2. make a "light" version of the app component that still has all widgets, and call findResultsState with that instead of the main application
  3. pass an extra prop to the findResultsState component which disables the problematic components
sonnd08 commented 2 years ago

@Haroenv Thanks, I have checked and seem like the 502 problem is from our nginx-ingress. But I would like to implement your approach later to prevent unnecessary API calling. Could you help me create an example for approach #2 and please describe deeper about #3?

sonnd08 commented 2 years ago

We temporarily bypass this by not rendering the child component until renderToString is finished.

Haroenv commented 2 years ago

That's indeed what I meant with option #3, thanks for updating, and sorry for not making an example for you yet