How to display register/signin errors on the client from a server action?

I'm using a server action on a register page to conditionally create db entries for a new user, and send out a verification email. My question is: How can I display an error on the register form like: "that username is already taken," based on the internal logic of the server action. Attached are my form and the server action respectively
No description
No description
17 Replies
sean
sean10mo ago
On your backend you need to return errors, and then on your frontend you could create a variable called "error" (or errors, if you wanna display multiple of them). And you can just conditionally check if that variable has an assigned value and then display an error component
machina
machina10mo ago
I’m more wondering how to do this with server actions. I’ve only done that with API routes that return NextResponses
sean
sean10mo ago
Exactly how I said, just use an error variable and change that Also remember that you should handle errors both on the backend and frontend
machina
machina10mo ago
How? just like return a JSON object?
sean
sean10mo ago
Yes And a status code that is different from 200
sean
sean10mo ago
If you don't know what status code to use, check out https://http.cat
HTTP Status Cats API
HTTP Cats
API for HTTP Cats
sean
sean10mo ago
Funnily enough there's also https://http.dog
machina
machina10mo ago
How do you intercept the response on the client? this is my current code:
export default async function Register() {

async function registerUser(data: FormData) {
"use server";

return new NextResponse(
JSON.stringify({
message: "user created successfully",
}),
{ status: 200 }
);
}

return (

<form action={registerUser} className="space-y-12 w-full sm:w-[400px]">
<div className="grid w-full items-center gap-1.5">
<Label>Name</Label>
<Input className="mb-6" name="name" required />
<Label>Email</Label>
<Input className="mb-6" name="email" type="email" required />
<Label>Password</Label>
<Input className="mb-6" name="password" type="password" required />
<Button type="submit">Register</Button>
</div>
</form>

);
}
export default async function Register() {

async function registerUser(data: FormData) {
"use server";

return new NextResponse(
JSON.stringify({
message: "user created successfully",
}),
{ status: 200 }
);
}

return (

<form action={registerUser} className="space-y-12 w-full sm:w-[400px]">
<div className="grid w-full items-center gap-1.5">
<Label>Name</Label>
<Input className="mb-6" name="name" required />
<Label>Email</Label>
<Input className="mb-6" name="email" type="email" required />
<Label>Password</Label>
<Input className="mb-6" name="password" type="password" required />
<Button type="submit">Register</Button>
</div>
</form>

);
}
so registerUser() is the server action, and inside the server action, I return a 200. How do I "catch" the response? so to speak Such that I can render a “registration failed” error In the page
sean
sean10mo ago
I'm at work so I can't really help you now, I'll take a look once I'm done @machina0 :)
machina
machina10mo ago
No worries at all
sean
sean10mo ago
Hey @machina0 I wrote a small example on how you can get errors from your server actions (HomePage)
"use client";

import { useState } from "react";
import { fetchYourData } from "./action";

export default function Home() {
const [error, setError] = useState("");

return (
<>
<div>{error}</div>
<button
onClick={async () => {
const data = await fetchYourData();
if (data.status === 200) {
setError("");
} else if (data.error) {
setError(data.error);
}
}}
>
Click me!
</button>
</>
);
}
"use client";

import { useState } from "react";
import { fetchYourData } from "./action";

export default function Home() {
const [error, setError] = useState("");

return (
<>
<div>{error}</div>
<button
onClick={async () => {
const data = await fetchYourData();
if (data.status === 200) {
setError("");
} else if (data.error) {
setError(data.error);
}
}}
>
Click me!
</button>
</>
);
}
(action.ts)
"use server";

export async function fetchYourData() {
const requestShouldFail = Math.random() < 0.5;
if (requestShouldFail) {
return {
status: 500,
error: "Internal server error",
};
} else {
return {
status: 200,
error: null,
};
}
}
"use server";

export async function fetchYourData() {
const requestShouldFail = Math.random() < 0.5;
if (requestShouldFail) {
return {
status: 500,
error: "Internal server error",
};
} else {
return {
status: 200,
error: null,
};
}
}
machina
machina10mo ago
thank you! @gigantino
sean
sean10mo ago
No problem :)
machina
machina10mo ago
is this how you do it, or do would you personally still use an api route with a client fetch to do most stuff i'm trying to understand what the best circumstances are to use server actions
sean
sean10mo ago
I wouldn't always use them personally, and I've yet to experiment enough (they are still experimental, so I haven't had a chance as of right now) If I were you I'd go with API routes I usually just prefer to fetch data on the server to pre-render it, and then if I need to make other requests I just do them with API routes. I honestly though love Svelte's approach of fetching data, and I think that the React and Next team should take inspiration from them
machina
machina10mo ago
I'm curious about svelte. I'll have to mess around with it someday
sean
sean10mo ago
You have to, it feels like black magic I don't get how it does what it does
Want results from more Discord servers?
Add your server
More Posts
depends_on alternative docker swarmUsing docker swarm for deployment where I'm using the docker-compose file I made before. Previoulsy Array<string> vs Record<key, true>?So, this is a call for mental help lol. First this is a taste question, is not a necesary question atailwind linter giving me a wrong warning?how would i go about combining this in tailwind? its giving me the warning of them being the same vaRegular Hexagon Plane using BufferGeometry in React Three FiberPretty self explanatory but i can't seem to wrap my head around this one last bit. I have all the mat3-env is giving error module is not defined in ES module scopei am trying to add t3-env in my project and it is giving me error ```js - error Failed to load next.Deploying to Vercel - now errors with build and dev part 2This is part 2, the error message ==== This is the output running either pnpm dev or build - info LoDeploying to Vercel - now errors with build and dev part 1I've been developing a T3 app, using first MySQL in Docker and then Postgres in Docker without any pCombining tRPC and Nextjs13 SuspenseHi there Did somebody succeed using Nextjs 13 App Routing Suspense features, like loading.tsx and tUse next-international without converting page.tsx or layout.tsx into client componentsI'm trying to use `next-international` but in their github readme https://github.com/QuiiBz/next-intCan t3 app be deployed on a traditional server and a tradition database?I kind of fear being locked into these solutions like planelscale, vercel, clerk etc. So, in case if