#Repository pattern warning useFetch with Nuxt 3.10

40 messages · Page 1 of 1 (latest)

torn thorn
#

Good morning,

In the latest version of Nuxt (3.10) warnings appeared when using useFetch outside of setup. This causes me problems because I have an architecture split via the pattern repository and there is no reason for this to give me warnings.
(PR #25071)

Here is an example of splitting that I have:

index.vue file:
try { data.value = await Repository.taxModule.taxClass.getAll({ ...defaultFetchTaxClassParams, ...options, }) } catch(e:any) { setRequestError(e) }
This method calls a utility class acting as a pass-through

Method called:
static async getAll( getTaxClassesOptions: API_taxClass_getTaxClassesOptions, ): Promise<ResultList<TaxClass>> { return await BaseRepository.getAllFactory<TaxClass>({ apiUrl: TaxClass.getApiUrlPrefix(), options: getTaxClassesOptions, adapter: TaxClassApiAdapters.formatTaxClassesResponse, }) }
And finally the getAllFactory method (calling my useApiFetch component)
`static async getAllFactory<T>({
apiUrl,
options,
adapter,
}: {
apiUrl: string
options?: any
adapter: (data: any, options?: any) => ResultList<T>
}): Promise<ResultList<T>> {
const url = ApiQuery.buildQueryString(apiUrl, options)
let response: unknown

    await useApiFetch(url)
        .catch((error) => {
            throw error
        })
        .then((res) => {
            response = res
        })
    return adapter(response, options)
}`

My useApiFetch is currently a composable allowing me to wrap the standard useFetch and add my token and other options
What should I change to keep this architecture while no longer having the warnings?
If I replace the useFetch in my composable with a $fetch, the SSR no longer happens at all..

Thanks in advance

torn thorn
#

Up please

faint crane
#

Would be easier to provide a running reproduction 🙂

torn thorn
#

This requires a lot of additional code and my api will not be accessible :/

#

What do you recommend in very large applications for code sharing at the API call level? (while keeping my custom composable which wrap useFetch to add the token in particular) ?

This warning can be disabled ?

torn thorn
#

Hello !

I made a repro to illustrate (in a very simplified way the problems following the update)

The problem will occurs when you click the button to make another call.

I have this kind of case in my application hundreds of times (whether to apply a filter, to make an API call after an action..)

I also need to keep my wrapper at useFetch to add my token (here I left it empty but it's to show my archi)

Thanks in advance !

https://stackblitz.com/edit/github-pgv3r7?file=app.vue

Create a new Nuxt project, module, layer or start from a theme with our collection of starters.

faint crane
#

@torn thorn You technically do a version of the mistake I show in my video, but "more complex" 😄
https://www.youtube.com/watch?v=njsGVmcWviY

💪🏻 useFetch is a mighty composable to fetch data in your Nuxt.js application. It can do so many things, from updating state to refreshing calls easily and even data caching is possible. But often I see that people misuse useFetch because it is so tempting to use all the features, even when you shouldn't. In this video I show the most common mist...

▶ Play video
torn thorn
#

Thank you for your feedback, and an additional subscription 😉

Wow
I'm going to have to rethink a lot of things to fix this.

If I understood correctly, when I need to make a call with immediate rendering (SSR) I must go through the useFetch, in all other cases $fetch ?

Would it be okay to pass a boolean to my functions to say to use useFetch or $fetch depending on where the calls are made ?

faint crane
#

So you don't want to call useFetch in a click handler

#

instead, you would want to use fetch there

#

Would it be okay to pass a boolean to my functions to say to use useFetch or $fetch depending on where the calls are made ?

From an architectural point, these are two very different things (function vs. composable). I'd not do that

#

instead, use your repository pattern fully based on $fetch, then use useAsyncData to call the pattern 🙂

torn thorn
#

The problem is that if I use $fetch in my wrapper, I will no longer have a call that will be made in SSR?

I don't really see how I could use useAsyncData to call the pattern
Really thank you for taking the time to answer me

faint crane
#

which will be "under the hood":

#

useAsyncData(() => $fetch('/url'/, {...}))

torn thorn
#

Okay, I see the idea. I will try to set this up today. I'll tell you what happens 🙂

torn thorn
faint crane
#

@torn thorn I'll release a video about it tomorrow 😄

#

As I got quite some requests on that 😄

torn thorn
#

Oh great, I can't wait to see this!
Hoping to get over this problem very soon 🤗

faint crane
#

💻 The repository pattern is a popular way to abstract your API calls away and provide a descriptive way to retrieve or send data. But how would you implement it in Nuxt? And should you use composables or $fetch for it? This video will give answers to all the questions!

Key points:
🎛️ Implementing the repository pattern in Nuxt
🔛 Creating our ow...

▶ Play video
#

(live at 3pm)

torn thorn
#

Yeahhhh

torn thorn
#

Hello @faint crane

it's me again 🙂

Thank you again for your video, it’s very interesting!
I have a question because in my implementation I also transform the data before returning it. How to do with the implementation so that the returned data is well transformed?

torn thorn
faint crane
#

try

#
<template>
  <div>
    <button @click="fetchOtherTodo">Fetch other todo</button>
    <div>{{ localTodo ?? 'no todo' }}</div>
  </div>
</template>

<script setup lang="ts">
import { Todo } from './entities/todo';

const { $api } = useNuxtApp();
const todoRepo = repository($api);

const localTodo = useState<Todo | null>('todos', () => null);
const fetchTodo = async (todoId: number) => {
  try {
    const data = await todoRepo.getOne(todoId)
    localTodo.value = data;
  } catch (e: any) {
    console.error(e);
  }
};

const fetchOtherTodo = async () => {
  const randomId = Math.floor(Math.random() * 10) + 2;
  await fetchTodo(randomId);
};

await fetchTodo(1);
</script>
torn thorn
#

With your proposal I no longer have the warning, however the first call is made on the client side whereas previously it was done on the server side :/

faint crane
#

I'd use useAsyncData instead there 😄

#

(with a parameter + watch) for example

torn thorn
#

I also tried with useAsyncData and either I got the warning or the first call is only made on the client side
I must really be doing something wrong ^^

torn thorn
#

wow it works well with this implementation, awesome!

I'm going to look into this and try to implement it on a small part of my application!

#

A big thank you 🤗