Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleaner way using custom fetch #8

Open
xdiegom opened this issue Apr 23, 2024 · 2 comments
Open

Cleaner way using custom fetch #8

xdiegom opened this issue Apr 23, 2024 · 2 comments

Comments

@xdiegom
Copy link

xdiegom commented Apr 23, 2024

Hi @Atinux! Hope you are doing well.

I was wondering if there is an update about creating a custom fetch composable that adapts the current Nuxt version 3.10.X because I believe your blog post is a bit behind from current changes and right know the Nuxt vesion I am using is showing a warning that I haven't solved which is [nuxt] [useFetch] Component is already mounted, please use $fetch instead. See https://nuxt.com/docs/getting-started/data-fetching.

I have followed the videos that the community suggest in this nuxt issue but the warning persists.

Thanks!

@Atinux
Copy link
Owner

Atinux commented Apr 26, 2024

Where do you use useAPI @xdiegom ?

This should be used only for fetching the initial data of the component

@xdiegom
Copy link
Author

xdiegom commented Apr 27, 2024

Hi @Atinux , thanks for your quick response. I appreciate 🙌🏼.

Specific installed nuxt version: 3.10.1

Basically I use it in components, plugins or middleware like documentation suggests when using useFetch. Because custom useApi composable uses useFetch():

useFetch is a composable meant to be called directly in a setup function, plugin, or route middleware. It returns reactive composables and handles adding responses to the Nuxt payload so they can be passed from server to client without re-fetching the data on client side when the page hydrates.

The warning shows up when using in the client side, for example a Login form action button
I understood that the reason of creating a customFetch is to reuse it in different parts of the application.

This is my useApi composable adapted to the current nuxt 3 version I have installed

// composable/useApi.ts 
export async function useApi<T>(
  path: string,
  options: UseFetchOptions<T> = {},
  prefix: string = 'api'
) {
  const config = useRuntimeConfig();

  const apiUrl = config.public.baseURL + '/' + prefix

  const jwt = useCookie('AUTH-TOKEN', {
    sameSite: 'lax',
    secure: true
  });

  const headerAuthorization: {
    Authorization?: string
  } = {}

  if (jwt.value) {
    headerAuthorization.Authorization = `Bearer ${jwt.value}`
  }

  let headers: any = {
    accept: "application/json",
    referer: config.public.appUrl,
    ...(headerAuthorization ?? { headerAuthorization })
  }

  return useFetch(path, {
    baseURL: apiUrl,
    watch: false,
    ...options,
    headers: {
      ...headers,
      ...options?.headers
    },
  })
}

Example of use:

// composable/useAuthentication.ts 

interface Profile {
  id: string,
  username: string,
  name: string
}

export default function () {
  const profile = useState<Profile>(() => ({}));

  const login = async (username: string, password: string): Promise<boolean> => {
    interface LoginResponse {
      token: string
    }

    const { data, status } = await useApi<LoginResponse>('login', {
      body: {
        username,
        password
      },
      method: "POST"
    })

    if (status.value === 'success') {
      const token = useCookie('AUTH-TOKEN', {
        sameSite: "lax",
        secure: true
      })

      token.value = data.value.token;

      return true

    }

    return false;
  }

  const getProfile = async (): Promise<void> => {
    const { data } = await useApi<Profile>('profile')
    profile.value = data.value.data;
  }

  return { login, getProfile, profile }
}

‼️ Here is where the warning is showing, when clicking the button that triggers the handleSubmit() function

// BaseLoginForm.vue
<template>
    <form @submit.prevent="handleSubmit" class="w-full space-y-3 flex flex-col items-center px-8">
        <BaseInput class="w-full" label="username" input-id="username" v-model="username">
        </BaseInput>
        <BaseInput type="password" class="w-full" label="password" input-id="password" v-model="password">
        </BaseInput>

        <BaseButton type="submit" class="w-full">
            Login
        </BaseButton>
    </form>
</template>

<script lang="ts" setup>
const { login } = useAuthentication();
const username = ref();
const password = ref();

const handleSubmit = async () => {
      await login(username.value, password.value);
}
// middleware/auth.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
    const { isLoggedIn, getProfile } = useAuthentication();

    if (process.server && !isLoggedIn.value) {
        await getProfile()
    }
})

Thanks again for your reply.

Regards,
Diego

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants