Fetch Data server and client side module recommended way

I am building a querybuilder for Craft CMS and I need to somehow make fetches on client and server side. I tried to do that with useFetch like that
async function fetchFn(url: string): Promise<FetchResult> {
const { data, error } = await useFetch(url)
return { data, error }
}
async function fetchFn(url: string): Promise<FetchResult> {
const { data, error } = await useFetch(url)
return { data, error }
}
But that only works on client side?! I am confused. What is the recommended way to do that? Maybe like that? https://nuxt.com/docs/guide/recipes/custom-usefetch#custom-usefetch
Nuxt
Custom useFetch in Nuxt · Recipes
How to create a custom fetcher for calling your external API in Nuxt 3.
5 Replies
kapa.ai
kapa.ai2mo ago
Hi @Samuelreichoer. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To fetch data on both the server and client side in Nuxt 3, especially when working with a CMS like Craft CMS, the recommended approach is to use useAsyncData or a custom wrapper around it. The useFetch composable you tried is primarily designed for making HTTP requests to URLs, which may not be the most suitable for your Craft CMS query builder. Here's the recommended approach: 1. First, create a custom composable that wraps useAsyncData. This allows you to encapsulate your Craft CMS query logic and reuse it across your application. 2. Inside this custom composable, you can use the Craft CMS API or SDK to fetch data. Here's an example of how you might structure this:
import { useAsyncData } from '#app'

export function useCraftQuery(query) {
return useAsyncData(
`craft-query-${JSON.stringify(query)}`,
() => {
// Here, use your Craft CMS SDK or API to execute the query
// For example:
return craftClient.query(query)
}
)
}
import { useAsyncData } from '#app'

export function useCraftQuery(query) {
return useAsyncData(
`craft-query-${JSON.stringify(query)}`,
() => {
// Here, use your Craft CMS SDK or API to execute the query
// For example:
return craftClient.query(query)
}
)
}
This approach is indeed similar to the custom useFetch example in the Nuxt documentation (https://nuxt.com/docs/guide/recipes/custom-usefetch#custom-usefetch) you referenced. It allows you to create a reusable composable that works on both the server and client sides. To use this in your components:
const { data, error, refresh } = await useCraftQuery({
// Your Craft CMS query parameters here
})
const { data, error, refresh } = await useCraftQuery({
// Your Craft CMS query parameters here
})
This method ensures that: 1. The data is fetched on the server-side during SSR. 2. The result is properly serialized and sent to the client. 3. On the client-side, it reuses the server-fetched data without making a duplicate request. 4. You can still refresh the data on the client-side when needed. Remember, the key here is using useAsyncData, which is designed to work universally (both server and client side) and integrates well with Nuxt's SSR capabilities Nuxt Data Fetching (https://nuxt.com/docs/getting-started/data-fetching#useasyncdata). By following this pattern, you should be able to create a query builder for Craft CMS that works efficiently in your Nuxt 3 application on both the server and client sides. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1065266379382587422> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Samuelreichoer
SamuelreichoerOP2mo ago
@kapa.ai Can you refactor my code to use asyncQuery? async function fetchFn(url: string): Promise<FetchResult> { const { data, error } = await useFetch(url) return { data, error } } export function useCraftQuery<T extends ElementType>(elementType: T) { const queryBuilder = useCraftUrlBuilder(elementType) return { ...queryBuilder, async one() { const url = queryBuilder.buildUrl('one') return await fetchFn(url) }, async all() { const url = queryBuilder.buildUrl('all') return await fetchFn(url) }, } }
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Certainly! I can help you refactor your code to use useAsyncData instead of useFetch. This approach will work better for both server-side and client-side data fetching in Nuxt 3. Here's how you can refactor your code:
import { useAsyncData } from '#app'

export function useCraftQuery<T extends ElementType>(elementType: T) {
const queryBuilder = useCraftUrlBuilder(elementType)

return {
...queryBuilder,

one() {
const url = queryBuilder.buildUrl('one')
return useAsyncData(`craft-query-one-${elementType}`, () => $fetch(url))
},

all() {
const url = queryBuilder.buildUrl('all')
return useAsyncData(`craft-query-all-${elementType}`, () => $fetch(url))
},
}
}
import { useAsyncData } from '#app'

export function useCraftQuery<T extends ElementType>(elementType: T) {
const queryBuilder = useCraftUrlBuilder(elementType)

return {
...queryBuilder,

one() {
const url = queryBuilder.buildUrl('one')
return useAsyncData(`craft-query-one-${elementType}`, () => $fetch(url))
},

all() {
const url = queryBuilder.buildUrl('all')
return useAsyncData(`craft-query-all-${elementType}`, () => $fetch(url))
},
}
}
Let's break down the changes: 1. We've removed the fetchFn function as it's no longer needed. 2. Instead of using useFetch, we're now using useAsyncData combined with $fetch. This is the recommended approach for Nuxt 3 as per the documentation (https://nuxt.com/docs/getting-started/data-fetching#useasyncdata). 3. The one and all methods are no longer async functions. Instead, they return the result of useAsyncData directly. 4. We're using unique keys for each useAsyncData call (craft-query-one-${elementType} and craft-query-all-${elementType}). This helps Nuxt cache and deduplicate requests efficiently. 5. The $fetch function is used within the callback passed to useAsyncData. This function is globally available in Nuxt 3 and is used for making HTTP requests Nuxt $fetch (https://nuxt.com/docs/api/utils/dollarfetch). To use this refactored useCraftQuery, you would do something like this:
const { data, error, refresh } = useCraftQuery('yourElementType').one()
// or
const { data, error, refresh } = useCraftQuery('yourElementType').all()
const { data, error, refresh } = useCraftQuery('yourElementType').one()
// or
const { data, error, refresh } = useCraftQuery('yourElementType').all()
This refactored version will work correctly on both the server and client sides, leveraging Nuxt 3's data fetching capabilities and SSR features. It also maintains the structure of your original useCraftQuery function while making it more Nuxt 3 friendly. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1065266379382587422> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server