N
Nuxt2w ago
o.m

What's causing the api call error when using composables?

I have this code
// Fetch users data
const { data } = await authRegister(form.value);
console.log(data);
// Fetch users data
const { data } = await authRegister(form.value);
console.log(data);
Which doesn't work well when calling register api. I cant create a new user This is the composable code
import type { Form } from "~/types/auth";
export const authRegister = async (form: Form): Promise<any> => {
console.log("Form: ", form);
return await fetch("/api/auth/register", {
method: "POST",
body: JSON.stringify(form),
});
};
import type { Form } from "~/types/auth";
export const authRegister = async (form: Form): Promise<any> => {
console.log("Form: ", form);
return await fetch("/api/auth/register", {
method: "POST",
body: JSON.stringify(form),
});
};
This is my template. Notice that the commented code works but the authRegister does not
const handleSubmit = async () => {
// Check if passwords match
if (form.value.password !== form.value.confirm_password) {
error.value = "Passwords do not match";
return;
}

// Fetch users data
const { data } = await authRegister(form.value);
console.log(data);

// Fetch users data
// const { data } = await useFetch("/api/auth/register", {
// method: "POST",
// body: JSON.stringify(form.value),
// });

// Check if there is an error
if (data.value && "error" in data.value.body) {
error.value = data.value.body.error;
return;
}
};
const handleSubmit = async () => {
// Check if passwords match
if (form.value.password !== form.value.confirm_password) {
error.value = "Passwords do not match";
return;
}

// Fetch users data
const { data } = await authRegister(form.value);
console.log(data);

// Fetch users data
// const { data } = await useFetch("/api/auth/register", {
// method: "POST",
// body: JSON.stringify(form.value),
// });

// Check if there is an error
if (data.value && "error" in data.value.body) {
error.value = data.value.body.error;
return;
}
};
12 Replies
kapa.ai
kapa.ai2w ago
Hi @o.m. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
o.m
o.mOP2w ago
This is the api/auth/register.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event);
let user = null;

// Check if email and password are provided
if (body.email && body.password) {
const isExistingEmail = await prisma.users.findFirst({
where: {
email: body.email,
},
});

// Check if email already exists
if (isExistingEmail) {
return {
status: 400,
body: {
error: EMAIL_EXISTS,
},
};
}

// Create a new user
user = await prisma.users.create({
data: {
email: body.email,
password: body.password,
},
});
}

return {
status: 200,
body: {
user: user,
},
};
});
export default defineEventHandler(async (event) => {
const body = await readBody(event);
let user = null;

// Check if email and password are provided
if (body.email && body.password) {
const isExistingEmail = await prisma.users.findFirst({
where: {
email: body.email,
},
});

// Check if email already exists
if (isExistingEmail) {
return {
status: 400,
body: {
error: EMAIL_EXISTS,
},
};
}

// Create a new user
user = await prisma.users.create({
data: {
email: body.email,
password: body.password,
},
});
}

return {
status: 200,
body: {
user: user,
},
};
});
kapa.ai
kapa.ai2w ago
---------------------- The issue you're experiencing is related to how composables and asynchronous operations work in Nuxt 3. Let me explain the problem and provide a solution based on the knowledge sources. The main issue is that you're trying to use a custom composable (authRegister) that wraps the fetch function directly. This approach doesn't work well with Nuxt's built-in mechanisms for handling server-side rendering and client-side hydration. Here's why your code is not working as expected: 1. Composables in Nuxt 3 need to be called synchronously within the setup function or <script setup> block. They can't be wrapped inside other functions or used in an asynchronous context without special handling. Nuxt docs on auto-imports (https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables) explain this limitation. 2. Using fetch directly doesn't provide the benefits of Nuxt's data fetching system, such as deduplication of requests and proper handling during server-side rendering. Nuxt docs on data fetching (https://nuxt.com/docs/getting-started/data-fetching#the-need-for-usefetch-and-useasyncdata) explain why using useFetch or useAsyncData is recommended. To fix this issue, you have a few options: 1. Use useFetch directly in your component, as you've shown in your commented-out code. This is the simplest and recommended approach. 2. If you want to keep your authRegister composable, you should modify it to use useFetch instead of fetch. Here's how you can do that:
import { useFetch } from '#app'

export const useAuthRegister = (form: Form) => {
return useFetch("/api/auth/register", {
method: "POST",
body: form,
})
}
import { useFetch } from '#app'

export const useAuthRegister = (form: Form) => {
return useFetch("/api/auth/register", {
method: "POST",
body: form,
})
}
Then in your component:
const handleSubmit = async () => {
if (form.value.password !== form.value.confirm_password) {
error.value = "Passwords do not match";
return;
}

const { data, error: fetchError } = await useAuthRegister(form.value)

if (fetchError.value) {
error.value = fetchError.value.message
return
}

// Handle successful registration
}
const handleSubmit = async () => {
if (form.value.password !== form.value.confirm_password) {
error.value = "Passwords do not match";
return;
}

const { data, error: fetchError } = await useAuthRegister(form.value)

if (fetchError.value) {
error.value = fetchError.value.message
return
}

// Handle successful registration
}
This approach uses useFetch, which is designed to work correctly with Nuxt's server-side rendering and client-side hydration Nuxt docs on useFetch (https://nuxt.com/docs/api/composables/use-fetch). Remember that when using useFetch or any other Nuxt composable, they must be called at the top level of your setup function or <script setup> block, not inside other functions or async contexts Nuxt docs on composable usage (https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables). By following these guidelines, you should be able to resolve the API call error and successfully create a new user. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@674984670156423171> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
o.m
o.mOP2w ago
What is useNuxtApp().$auth ? @kapa.ai
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: Sorry @o.m, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
o.m
o.mOP2w ago
@kapa.ai what is useNuxtApp().$auth ?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- useNuxtApp().$auth is not a standard feature of Nuxt 3, but it appears to be a custom property added to the Nuxt application instance. Let me explain what useNuxtApp() is and how custom properties like $auth might be added to it. useNuxtApp() is a composable provided by Nuxt 3 that allows you to access the shared runtime context of the Nuxt application. This context includes various properties and methods that are available throughout your Nuxt app Nuxt docs on useNuxtApp (https://nuxt.com/docs/api/composables/use-nuxt-app). The $auth property you're asking about is likely a custom addition to the Nuxt app instance. This is typically done through a plugin or by using the provide method of the Nuxt app. Here's how it might have been added: 1. Through a plugin:
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.$auth = {
// Custom auth methods and properties
}
})
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.$auth = {
// Custom auth methods and properties
}
})
2. Using the provide method:
const nuxtApp = useNuxtApp()
nuxtApp.provide('auth', {
// Custom auth methods and properties
})
const nuxtApp = useNuxtApp()
nuxtApp.provide('auth', {
// Custom auth methods and properties
})
After adding a custom property like this, you can access it using useNuxtApp().$auth in your components, composables, or other parts of your Nuxt application Nuxt docs on providing helpers (https://nuxt.com/docs/guide/going-further/nuxt-app#providing-helpers). It's important to note that $auth is not a built-in feature of Nuxt, but rather a custom addition specific to your project or a third-party module you might be using. The exact functionality and properties of $auth would depend on how it was implemented in your specific Nuxt application. If you need more details about what $auth does in your particular project, you should check your project's plugins, modules, or documentation for any authentication-related setup. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@674984670156423171> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
o.m
o.mOP2w ago
@kapa.ai how do i register middleware?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To register middleware in Nuxt 3, you have several options depending on your specific needs. Here's how you can register different types of middleware: 1. Named Route Middleware: Place your middleware file in the middleware/ directory. Nuxt will automatically load and register it.
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Your middleware logic here
})

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Your middleware logic here
})

Then, use it in your pages with definePageMeta:
<script setup>
definePageMeta({
middleware: ["auth"]
})
</script>

<script setup>
definePageMeta({
middleware: ["auth"]
})
</script>

Nuxt docs on middleware (https://nuxt.com/docs/guide/directory-structure/middleware#usage) 2. Global Route Middleware: Add a .global suffix to your middleware file name in the middleware/ directory. This middleware will run on every route change.
// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Your global middleware logic here
})

// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Your global middleware logic here
})

Nuxt docs on global middleware (https://nuxt.com/docs/guide/directory-structure/middleware#global-route-middleware) 3. Inline Route Middleware: You can define middleware directly in your page components:
<script setup>
definePageMeta({
middleware: [
function (to, from) {
// Your inline middleware logic here
}
]
})
</script>

<script setup>
definePageMeta({
middleware: [
function (to, from) {
// Your inline middleware logic here
}
]
})
</script>

Nuxt docs on inline middleware (https://nuxt.com/docs/guide/directory-structure/middleware#example) 4. Dynamic Middleware Registration: You can also add middleware dynamically using the addRouteMiddleware() helper function, typically within a plugin:
// plugins/my-plugin.ts
export default defineNuxtPlugin(() => {
addRouteMiddleware('my-named-middleware', () => {
// Your middleware logic here
})

addRouteMiddleware('my-global-middleware', () => {
// Your global middleware logic here
}, { global: true })
})

// plugins/my-plugin.ts
export default defineNuxtPlugin(() => {
addRouteMiddleware('my-named-middleware', () => {
// Your middleware logic here
})

addRouteMiddleware('my-global-middleware', () => {
// Your global middleware logic here
}, { global: true })
})

Nuxt docs on adding middleware dynamically (https://nuxt.com/docs/guide/directory-structure/middleware#adding-middleware-dynamically) Remember that route middleware in Nuxt 3 runs within the Vue part of your Nuxt app and is different from server middleware. The middleware will receive the to and from route objects as arguments, allowing you to perform actions based on the navigation. Nuxt docs on middleware (https://nuxt.com/docs/guide/directory-structure/middleware) By using these methods, you can effectively register and use middleware in your Nuxt 3 application to run code before navigating to a particular route. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@674984670156423171> 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