xephyr
xephyr
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
@KiNFiSH I've refactored it to use authClient now, but I'm still curious why the server action wasn't working so I've recreated it. Let me know what you think 🙂
export const signInEmailSchema = z.object({
email: z.string().email({ message: "Invalid email address" }),
password: z.string(),
});

export const SignInForm: FC<ComponentPropsWithoutRef<"div">> = ({
className,
...props
}) => {
const signInEmail = async (prevState: unknown, formData: FormData) => {
"use server";

const submission = parseWithZod(formData, {
schema: signInEmailSchema,
});
if (submission.status !== "success") return submission.reply();

try {
await auth.api.signInEmail({
body: submission.value,
});
} catch (error) {
if (error instanceof APIError) {
return submission.reply({
formErrors: [error.message],
});
}
}

redirect("/");
};
const [state, formAction, pending] = useActionState(signInEmail, undefined);
const [form, fields] = useForm({
lastResult: state,
onValidate({ formData }) {
return parseWithZod(formData, { schema: signInEmailSchema });
},
shouldValidate: "onInput",
});

return (
<form action={formAction} id={form.id} noValidate onSubmit={form.onSubmit}>
...
</form>
);
};
export const signInEmailSchema = z.object({
email: z.string().email({ message: "Invalid email address" }),
password: z.string(),
});

export const SignInForm: FC<ComponentPropsWithoutRef<"div">> = ({
className,
...props
}) => {
const signInEmail = async (prevState: unknown, formData: FormData) => {
"use server";

const submission = parseWithZod(formData, {
schema: signInEmailSchema,
});
if (submission.status !== "success") return submission.reply();

try {
await auth.api.signInEmail({
body: submission.value,
});
} catch (error) {
if (error instanceof APIError) {
return submission.reply({
formErrors: [error.message],
});
}
}

redirect("/");
};
const [state, formAction, pending] = useActionState(signInEmail, undefined);
const [form, fields] = useForm({
lastResult: state,
onValidate({ formData }) {
return parseWithZod(formData, { schema: signInEmailSchema });
},
shouldValidate: "onInput",
});

return (
<form action={formAction} id={form.id} noValidate onSubmit={form.onSubmit}>
...
</form>
);
};
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
(I've switched to using authClient instead, ditched useActionState with server actions)
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
at least not for me
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
the session doesn't update though
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
i'm not sure where the cookies are supposed to be set
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
so the server action either returns a conform error response or redirects
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
using Conform on the client to manage the form error states
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
I think I'm misunderstanding something about how it's meant to set cookies, because I'm not using asResponse and returning it because it's in useActionState so it can't return Response
21 replies
BABetter Auth
Created by Henrik on 4/15/2025 in #help
Next.js server actions auth
21 replies
BABetter Auth
Created by xephyr on 4/15/2025 in #help
Anyone using auth.api in a server action with useActionState?
FWIW here's the action:
"use server";

import { APIError } from "better-auth/api";
import { redirect } from "next/navigation";
import { parseWithZod } from "@conform-to/zod";
import { auth } from "@/lib/auth";
import { signInEmailSchema } from "./schema";

export const signInEmail = async (prevState: unknown, formData: FormData) => {
const submission = parseWithZod(formData, { schema: signInEmailSchema });
if (submission.status !== "success") return submission.reply();

try {
await auth.api.signInEmail({
body: submission.value,
});
} catch (error) {
if (error instanceof APIError) {
return submission.reply({
formErrors: [error.message],
});
}
}

redirect("/");
};
"use server";

import { APIError } from "better-auth/api";
import { redirect } from "next/navigation";
import { parseWithZod } from "@conform-to/zod";
import { auth } from "@/lib/auth";
import { signInEmailSchema } from "./schema";

export const signInEmail = async (prevState: unknown, formData: FormData) => {
const submission = parseWithZod(formData, { schema: signInEmailSchema });
if (submission.status !== "success") return submission.reply();

try {
await auth.api.signInEmail({
body: submission.value,
});
} catch (error) {
if (error instanceof APIError) {
return submission.reply({
formErrors: [error.message],
});
}
}

redirect("/");
};
3 replies