Custom $fetch and Repository Pattern in Nuxt 3

Поділитися
Вставка
  • Опубліковано 9 лип 2024
  • 💻 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 own $fetch instance
    ‼️ Making sure that it works with composables and standalone
    👩‍💻 Building the demo app step by step
    ---
    Links:
    📺️ Do you use useFetch wrong?! - • You are using useFetch...
    🔗 Sebastien Chopin's blog post about custom $fetch - notes.atinux.com/nuxt-custom-...
    📺️ Class Serialization Errors - • Class Serialization wi...
    🔗 Code - github.com/manniL/alexander-l...
    🔗 My repository pattern blog post www.lichter.io/articles/nuxt-...
    Don't forget to hit that "Subscribe" button, ring the notification bell and give a thumbs up!
    🌐 Connect further:
    Website: www.lichter.io
    Twitter/X: / thealexlichter
    Twitch: / thealexlichter
    Chapters:
    00:00 Intro
    00:44 A warning when misusing useAsyncData or useFetch
    01:22 Demo app
    02:28 Implementing the repository pattern
    03:52 Passing a $fetch instance
    05:37 Creating our own $fetch instance
    06:35 Globally providing $fetch + using runtimeConfig
    09:47 Summary
    Keywords:
    repository pattern nuxt nuxt3 custom $fetch fetch
  • Наука та технологія

КОМЕНТАРІ • 91

  • @TheAlexLichter
    @TheAlexLichter  5 місяців тому +8

    Are you a fan of the repository pattern?

    • @Berk45632
      @Berk45632 5 місяців тому +1

      Can you have a video tutorial on Repository pattern itself? Coming from Android dev background, having repositories in Nuxt sounds amazing!

    • @chegunmoulero2737
      @chegunmoulero2737 4 місяці тому

      The fact that you put it in plugins, wouldn't it impact the page loading performance?

    • @zanfras1149
      @zanfras1149 4 місяці тому

      @@Berk45632 +1 on this.

    • @Tarabass
      @Tarabass 4 місяці тому

      Not at all. I have the feeling that a nuxt server api endpoint should be a better place for abstraction so devs should not care about which api is called in the hood. But maybe that's the wrong approach, I don't know.

    • @cybercowboy9214
      @cybercowboy9214 2 місяці тому +1

      I dislike the repository pattern; it seems to originate from seasoned developers who apply the same extensive pattern to all projects. I prefer modern tools like Nuxt, reactivity, and composables, and I'm not fond of developers from Java or C# backgrounds who come from their enterprise projects trying to impose their methods on every modern project, disrupting the architecture.
      Nuxt inherently provides good tools, and creating separate patterns alongside it feels like a waste of time to me.

  • @AlterMachKeinAuge
    @AlterMachKeinAuge 4 місяці тому +10

    Great video, Alex!
    I'd be thrilled to see you delve into more intricate scenarios, such as implementing the Repository Pattern with Pinia and Middleware.
    Moreover, it would be immensely beneficial if you could explore other best practice architectures for Nuxt3. Concepts like DDD and Hexagonal Architecture are often overlooked in the Nuxt community, and I believe your expertise could bridge that gap.
    Coming from a Spring Boot background myself, where detailed information is abundant, it's refreshing to see someone like you paving the way for similar depth in the Nuxt world.
    Thanks a ton for your content and take care! 👍

    • @TheAlexLichter
      @TheAlexLichter  3 місяці тому +1

      Thanks for the comment 🙏🏻
      I'll try to provide some more insights wrt DD/hexagonal architecture in e.g. a stream or similar. Might be tricky to cover in a 10 min video (except maybe as summary of the stream 🤔)

    • @AlterMachKeinAuge
      @AlterMachKeinAuge 3 місяці тому

      @@TheAlexLichter That would be awsome. Thanks

  • @npm_dev
    @npm_dev 4 місяці тому +1

    Thank you for video! Nice to see such good examples with patterns

  • @mikalai-hryb
    @mikalai-hryb 4 місяці тому +1

    Thank you for this hands-on video!
    Please continue creating more such videos because Nuxt is complex and it's not obvious how to use some features in the right way

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      Thanks, will do!
      Do you have specific features in mind that you'd like to see covered?

    • @devarloop1981
      @devarloop1981 4 місяці тому

      @@TheAlexLichter It would be awesome a video to learn when to fetch data with stores like pinia or simple fetch and paint requests

  • @fanreza404
    @fanreza404 5 місяців тому +1

    this is video i need, thanks as always

  • @tolgabeyazoglu536
    @tolgabeyazoglu536 5 місяців тому +4

    We should always support Alexi because good creating video

  • @tranphuocloc7972
    @tranphuocloc7972 5 місяців тому +1

    Great content.
    Thanks so much!!!

  • @Tarabass
    @Tarabass 4 місяці тому +2

    A bit late in the game, but thanks for this great video! It's very inspirational for me. Keep up the good work, it's much appreciated ❤

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Ah, not that late! Thanks a lot for the kind word and glad it was helpful 🙌🎉

  • @JulioCampoSwork
    @JulioCampoSwork 5 місяців тому +3

    Amazing, this is some hard to me but i know someday i understand 100% and use it, thanks a lot

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому +1

      Happy to help! Don't worry if not everything is clear 100%. It will come by the time!

  • @jon8236
    @jon8236 5 місяців тому +2

    Great video as usual👍Would love to see a video on Tanstack Query for vue and nuxt.

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому +2

      Thank you! Yes - noted, especially after the perf gain PR :D github.com/TanStack/query/pull/6657

  • @silvesterwali6565
    @silvesterwali6565 5 місяців тому +1

    Amazing bro....

  • @alimaher1
    @alimaher1 5 місяців тому +2

    That was awesome! Thanks, Alexander!
    I was thinking of a similar idea yesterday but ended up building a wrapper around useFetch, with my custom/default api handling. Not sure how to feel about that but what do you think?

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому +1

      Answered in ua-cam.com/video/jXH8Tr-exhI/v-deo.html&lc=UgwRJDscxblXjqcGla54AaABAg.A-bGQOKRuhIA-bdfDQjom3
      TL;DR - Better do it "one level lower" and write a composable based on it so you can use the $fetch wrapper in event handlers etc.

  • @miguelcassimiro8103
    @miguelcassimiro8103 5 місяців тому +1

    Hi Alexander, it’s been really nice seeing your videos with this kind of topic from Nuxt. Excellent job.
    I starting to use some of this features recently and I get confused with one thing: $fetch is more recommend to use on server side and useAsyncData it’s more recommended when waiting or watching some client action (click or reactive data)?
    I really don’t know actually how to separate things on client and server correctly . Thanks for the help

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +2

      Hey Miguel! The idea is that useAsyncData/useFetch should be used when you want to fetch content for SSR (it is automatically included) or when you need reactivity for (re-)fetching content. You use $fetch commonly for user interaction
      More details in ua-cam.com/video/njsGVmcWviY/v-deo.html

    • @miguelcassimiro8103
      @miguelcassimiro8103 4 місяці тому +1

      @@TheAlexLichternice, I'll check it out. Thanks a lot and please continue with the content.

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Will do ✌

  • @dayanbalevski4446
    @dayanbalevski4446 5 місяців тому +2

    I am currently trying out a repository pattern using a composable, for example friendships, it holds all of my api calls related to managing friendships like listFriends, AddFriend, RemoveFriend etc.
    I am just not sure about error handling if catching errors should exist in the repository or is the repository just providing the promises and any handling is done by the caller. Also I am wondering about redirecting users to error pages if the session is expired for example. Would a global error handling config in the case of axios be the go to - what about fetch?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Hey Dayan!
      Error's can be caught when using the repo *or* when using the composable. I'd catch them context-dependent.
      For redirecting + session expired: You could add that mechanism in the nuxt plugin I suppose

  • @AksoomHussain7866
    @AksoomHussain7866 4 місяці тому

    great video , many month ago i tried making custom api plugins but getting the token or other data from localstorage or DBindex not work properly even using pinia then i shift to composable API now it work fine but still i miss the plugin advantage and i use nuxt static site to deploy in the app enclosure

    • @TheAlexLichter
      @TheAlexLichter  3 місяці тому

      Communicating further can be tricky but it should be doable in a plugin too, e.g. a client-side only plugin with a stub on the server (as there is no localstorage on the server).
      But glad you got it working 👍🏻

  • @mervasdayi
    @mervasdayi 5 місяців тому +1

    nuxt-api-party module is my way to go for such case

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Yes, was mentioned a few times and is a good option for sure!

  • @mrsofiane
    @mrsofiane 2 місяці тому +1

    Thx for the video, why not using it as composable ? why plugin is better fit here ? thx

    • @TheAlexLichter
      @TheAlexLichter  2 місяці тому +1

      You can also use composable but it is easier to provide the fetch fn to the application "as a whole" if you need it throughout the app, so you don't have to initialize it again and again 😋

  • @diegomelgar2696
    @diegomelgar2696 4 місяці тому +1

    I'm still struggling with this :(.
    I can't get rid off the warning, and I have followed what Sebastian said in the blog you said.
    I want to use my composables to fetch data and use my custom useAPI composable which uses the custom API plugin and I don't know what am I doing wrong.
    Ironic is that, following Sebastian blog, he uses useFetch() in the custom useAPI composable and with that I still have the warning!

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Do you have a minimal reproduction by any chance? Feel free to send me a DM on Discord or Twitter/X!

  • @ragura
    @ragura 4 місяці тому +1

    This was easy enough to implement, thanks! I used to do this with Axios back in the Middle Ages and the pattern translates well to Nuxt. One question: is there really no way to have $api available as an auto import instead of having to import it manually everywhere?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      You are welcome!
      Hmm, technically you could create your own composable which can auto import it, e.g. `const $api = useApi()` where useApi is just `export const useApi = () => { return useNuxtApp().$api }` 👀
      Just important to call that on top as written and then call the function in event handlers. Don't call the composable in the handler itself

    • @ragura
      @ragura 4 місяці тому

      @@TheAlexLichter Thanks for the fast reply so late at night :D I can see how it's a clever workaround, but unless I'm misunderstanding where to place the `const $api = useApi()` line, it's a minor gain since you still have to write the `useApi()` line where you want to use $api? Not quite as quick and easy as having `$fetch` available everywhere out of the box. But I guess it's just not possible to register $api globally and provide types through type declaration in a .d.ts file somewhere?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      @@ragura Yes, you still need to write it unfortunately. I wonder if we could use sth. like unimport which imports e.g. computed, ref etc. etc. for this case 🤔

  • @alexcroox
    @alexcroox 4 місяці тому

    One thing I'm struggling with is how do I get the loading state of a POST api in this pattern if I'm calling with a submit function?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      create a ref with a "state" (or simple: boolean for loading true/false) and set the value according to what happens :)

  • @arnaudkinnoudo3351
    @arnaudkinnoudo3351 2 місяці тому

    Thanks for this great content @TheAlexLichter 🙏. I have a small question: How to pass an auth token from localstorage or cookie ? (please explain both cases if possible).

    • @TheAlexLichter
      @TheAlexLichter  Місяць тому +1

      You are welcome!
      You can use useLocalStorage/useCookie to read it 😋

  • @brahim_boussadjra
    @brahim_boussadjra 4 місяці тому +1

    Awesome video,thanks, is it possible to do a video about Domain Driven Design in Nuxt3?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      You are welcome! I'd have to do a little bit more research, but probably. First, an intro video about Nuxt Layers though (which is an important feature for DDD in Nuxt)

  • @zanfras1149
    @zanfras1149 4 місяці тому

    Great video as always Alex! Thank you
    I have a question, if I may. What would be a good approach handling errors in script setup using LazyAsyncData (to not block navigation) where we cannot really await for the response. Therefore I cannot check for error directly after the request.
    One way would be watcher on error I guess but it gets ugly IMO. Thanks!😊

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      You still *can* await these. They should be blocking on the server (when not using server:false) anyway, but lazy === non-blocking on client.
      But if that doesn't work then yes, a watcher it is 🙌

    • @zanfras1149
      @zanfras1149 4 місяці тому

      Ah, I see! gottcha. Thanks a lot.

  • @tranphuocloc7972
    @tranphuocloc7972 5 місяців тому +1

    Great content!
    But i wonder what is good way to write a post api , in top of script or in function i want to call post api. If in top of script, how to control parameter , i have to define a ref then pass it to repo?
    Hope get your answer, thanks so much.

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому +1

      Thanks!
      It depends a bit on your abstraction but you should never call a composable in such a handler function. See ua-cam.com/video/njsGVmcWviY/v-deo.html

    • @tranphuocloc7972
      @tranphuocloc7972 5 місяців тому

      @@TheAlexLichter yes, because i saw this video so i create this question, if i don't call in such a handler function, i need a state like ref to pass parameter to fetch, is it mess?

  • @MrGuiabraun
    @MrGuiabraun 4 місяці тому

    I just wanted to understand why when I try to import nitropack it says "Cannot find module 'nitropack' or its corresponding type declarations." in the latest version of Nuxt

    • @TheAlexLichter
      @TheAlexLichter  3 місяці тому +1

      You might need to add it to your dependencies manually (even though it *is* included already)

  • @randomtimessomehow
    @randomtimessomehow 5 місяців тому +1

    I have a question although it might not be exactly regarding the topic you've covered in this video: I'm using multiple composables which and some of these do an API call to my Supabase database through the Supabase Nuxt module. For instance, the composable "useIndustry" returns a variable "industries". Internally, inside the composable there is a function called "getIndustries" which receives the industries from the Supabase database. Now, I would like to block the navigation until variable industries has been set/getIndustries has been finished. How can I do this with the composable pattern?

    • @chegunmoulero2737
      @chegunmoulero2737 5 місяців тому +2

      If you are using script with setup, just call your composable function inside useAsyncData on top level with await keyword

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      @@chegunmoulero2737^This should work, yes

  • @user-qb7yc3qg3b
    @user-qb7yc3qg3b 5 місяців тому +1

    creating composable of fetch instance good way to organize fetching? or plugin better to use than useApi composable?
    what patterns we can use to implement some api logic in nuxt app?
    thank you! good video!

    • @alimaher1
      @alimaher1 5 місяців тому +1

      I have the same question

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому

      Just building a composable is not enough when you need to e.g. post data for a form submission or on button click as I've explained it in ua-cam.com/video/njsGVmcWviY/v-deo.html
      That's why building it so you can use it as part of a composable *or* as simple "wrapper around $fetch" is superior.

    • @user-qb7yc3qg3b
      @user-qb7yc3qg3b 5 місяців тому

      @@TheAlexLichter yeah, i create fetch instance in useApi composable, and in another composables useUserApi, useAuthApi i use it to make some api service. But i dont know is it a good way? Because every time i use method from api service i create new instance, but if i implement wrapper in plugin there is creating once. Idk composable wrapper bad for performance or not)

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому

      Do you have an examplary implementation you can share via nuxt.new/s/v3 ?

  • @yuriachilles6701
    @yuriachilles6701 Місяць тому

    Can you talk about how to organize api calls in a real project (folders, file ....)? I would like to refer to it for use in my projects. Thanks a lot 😀

    • @TheAlexLichter
      @TheAlexLichter  Місяць тому

      I hope to cover that while building a real project (need some time for it again tough)

  • @DaviesMaina
    @DaviesMaina 4 місяці тому

    Good!
    can you talk about reducing bundle size in a Nuxt application?

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      Yes, absolutely! I covered it a bit in ua-cam.com/video/laRJNkG_wls/v-deo.html but more is coming!

  • @RiadDZz
    @RiadDZz 4 місяці тому

    Hello Alex can you please tell me if it's okay to make a composable like so instead of a plugin ?,
    Here useAuth() is a Pinia store containing auth information like logged and the access token.
    export function $api(
    request: Parameters[0],
    opts?: Parameters[1],
    ) {
    const auth = useAuth()
    return $fetch(request, {
    ...opts,
    headers: {
    Authorization: auth.logged ? `Bearer ${auth.accessToken}` : '',
    ...opts?.headers,
    },
    })
    }

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      You can, but then you *can't* use it for e.g. sending a form "easily".

  • @matheusteixeira4161
    @matheusteixeira4161 4 місяці тому

    I did the same as you, but still having this error:
    const { $api } = useNuxtApp()
    const userRepo = repository($api)
    Argument of type 'unknown' is not assignable to parameter of type '$Fetch'.ts(2345)

    • @matheusteixeira4161
      @matheusteixeira4161 4 місяці тому

      The error is when I try to pass $api as repository parameter

    • @matheusteixeira4161
      @matheusteixeira4161 4 місяці тому +2

      Never mind. It was just a vscode bug. When i reloaded the application the error was gone

    • @TheAlexLichter
      @TheAlexLichter  4 місяці тому +1

      Perfect 👍

  • @unzarisan
    @unzarisan 5 місяців тому

    Cool stuff as usual Alex. Wanted to find out, what is the difference was when returning a $fetch as opposed to a $fetch.create() and if using a composable instead of a plugin was okay too

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому

      Thank you 🙌
      $fetch is fine if you don't need any customizations (e.g. refresh token logic, custom base URL or similar). $fetch.create is like $fetch, but with other defaults 👍
      Answered the composable vs. plugin topic in ua-cam.com/video/jXH8Tr-exhI/v-deo.html&lc=UgwRJDscxblXjqcGla54AaABAg
      TL;DR - You want to be able to use your implementation often without using a composable.

    • @unzarisan
      @unzarisan 5 місяців тому

      ​@@TheAlexLichter thanks a lot for the tip👍

  • @Indam1
    @Indam1 3 місяці тому

    Thank you very much for the great videos!
    Is it good practice to create a repository e.g. for supabaseClient? Composable useSupabaseClient is pretty nice to use, but It doesn't seem to be clean having big call chains like `supabase.storage.from('blablabla').remove('blablabla')` in different places

    • @TheAlexLichter
      @TheAlexLichter  3 місяці тому +1

      Happy they help 👏🏻
      You can write a composable as abstraction around that if you want ☺️

  • @HBILAL99
    @HBILAL99 5 місяців тому

    Hey alex i'm having problem in nuxt middleware I've auth.global.ts
    if (!token && to.path !== '/auth/login') {
    return navigateTo('/auth/login')
    }
    it's working but when i type localhost:3000/dashbard and hit enter it render dashboard for a while then goto login page
    I've also tried " if (process.server) return " but still same issue

    • @TheAlexLichter
      @TheAlexLichter  5 місяців тому

      Hey!
      Best would be to provide a reproduction and post in the Nuxt Discord or as GitHub discussion. That'll be easier to debug than as YT comment 👍

    • @HBILAL99
      @HBILAL99 5 місяців тому

      @@TheAlexLichter can you please create a video on it?
      the problem is when ever i goto the protected rutes through browser it still render for some while then redirected to login page

    • @naseefpv1
      @naseefpv1 5 місяців тому

      ​@HBILAL99 i think, it depends up on where do you store your token. (Localstorage, cookie). Make sure your token value is available in the middleware.

    • @HBILAL99
      @HBILAL99 4 місяці тому

      @@naseefpv1 no even if you create local variable like let auth = false then still same problem