nuxt-modules / algolia

🔎 Algolia module for Nuxt
https://algolia.nuxtjs.org/
MIT License
185 stars 32 forks source link

Best way to implement SSR-safe search that can be refined client-side #174

Closed maximilliangeorge closed 10 months ago

maximilliangeorge commented 10 months ago

Hi guys, thanks for this plugin to help me streamline integration with Algolia!

I just have a question regarding usage for SSR. Let's say I have a listing page that should show some initial results before the user has started to refine the search. In the example provided in the docs I can implement it this way below:

<script setup lang="ts">
const { result, search } = useAlgoliaSearch('test_index') // pass your index name as param
const { data } = await useAsyncData('ssr-search-results', () => search({ query: 'Samsung' }))
</script>

However, this example exposes search results in two separate places: in the result variable and in the data variable? Which one should I use in the template?

Since I want the search results to be initially rendered, I'm guessing I should be using data as this ensures the data is pre-rendered server side. However, the implementation above doesn't make it easy to update data client-side. It is also unclear if we actually need to use result for anything.

I'm toying around with an alternative implementation below but I'm not sure if I'm missing some important nuance:

<script setup lang="ts">

// I'm omitting `result` here, since it isn't used
const { search } = useAlgoliaSearch('test_index')

// storing data in a separate ref
const data = ref<any>()

// ssr
const res = await useAsyncData('ssr-search-results', () => search({ query: 'Samsung' }))
data.value = res.data

// user refinement
async function doClientSideSearch () {
  const res =  await search({ query: 'Samsung' }))
  data.value = res.data
}

</script>

Am I missing something, or is this a legit way to implement an SSR-proof search that can be refined further client-side?

Baroshem commented 10 months ago

Hey,

Good question!

What about using this approach?

<script setup lang="ts">
const { data, refresh } = await useAsyncAlgoliaSearch({ indexName: 'test_index', query: 'Samsung' })
</script>
<template>
  <div>{{ data.value.hits }}</div>
  <button @click="refresh">Refresh data on frontend</button>
</template>

https://nuxt.com/docs/api/composables/use-async-data#return-values

You can also watch for certain params https://nuxt.com/docs/api/composables/use-async-data#example-with-watching-params-change

Let me know if that answers your question :)

maximilliangeorge commented 10 months ago

Ah thanks! I didn't realise that useAsyncAlgoliaSearch mimicks useAsyncData in that it exposes a refresh/execute method.

That will cover my use case. Is it also possible to pass a watch param to useAsyncAlgoliaSearch, or does that have to go via a plain useAsyncData?

Baroshem commented 10 months ago

It is not possible to do that with useAsyncAlgoliaSearch but as you mentione,d it is just a wrapper around useAsyncData, so you should be able to use it easily.

Just keep in mind that you would need to set different transported for SSR as shown here (https://github.com/nuxt-modules/algolia/blob/c4f576266a0d6ae7477228e0ec056d21aac1af32/src/runtime/composables/useAsyncAlgoliaSearch.ts#L16). Otherwise you would get an error.

Baroshem commented 10 months ago

Hey @maximilliangeorge

I will close this question as resolved. If you will have any other questions in the future, do not hesitate to create issue / discussion and I will be happy to answer :)