#Show error in client side while having serverside page
1 messages · Page 1 of 1 (latest)
To show an error on the client side while having server-side code, you can utilize the built-in error handling mechanisms provided by Next.js. Specifically, you can use the Error component from next/error to render error messages on the client side.
Here's how you can modify your login function to handle errors and display them on the client side:
- Import the
Errorcomponent fromnext/error. - Catch errors in your
loginfunction and set the error state. - Render the
Errorcomponent conditionally based on the error state.
Here's an updated version of your LoginForm component:
import { useState } from "react";
import { Button, Form, Input, message } from "antd";
import { toUpperCase } from "../../utils";
import FormItem from "antd/lib/form/FormItem";
import InputPassword from "antd/lib/input/Password";
import { Icons } from "../Icons";
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import Link from "next/link";
import Error from 'next/error';
interface LoginFormValues {
email: string;
password: string;
}
const LoginForm = () => {
const [error, setError] = useState(null);
const login = async (values: LoginFormValues) => {
"use server";
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/auth/login`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
}
);
if (!response.ok) {
throw new Error("ელ.ფოსტა ან პაროლი არასწორია!");
}
const data = await response.json();
cookies().set("accessToken", JSON.stringify(data.accessToken));
cookies().set("refreshToken", JSON.stringify(data.refreshToken));
cookies().set("user", JSON.stringify(data.user));
redirect("/");
} catch (err) {
setError(err.message);
}
};
return (
<>
{error && <Error statusCode={500} title={error} />}
<Form onFinish={login} size="large">
<FormItem
name="email"
rules={[
{ required: true, message: "ელ.ფოსტა აუცილებელია!", type: "email" },
]}
>
<Input placeholder={toUpperCase("ელ.ფოსტა")} />
</FormItem>
<FormItem
name="password"
rules={[{ required: true, message: "პაროლი აუცილებელია!" }]}
>
<InputPassword placeholder={toUpperCase("პაროლი")} autoComplete="on" />
</FormItem>
<Button type="primary" htmlType="submit" icon={<Icons.sendIcon />}>
{toUpperCase("გაგზავნა")}
</Button>
</Form>
</>
);
};
export default LoginForm;
In this example:
- The `useState` hook is used to manage the error state.
- The `Error` component from `next/error` is used to display the error message on the client side.
- The `login` function catches any errors and sets the error state, which triggers the rendering of the `Error` component.
This approach ensures that errors are handled gracefully and displayed to the user without changing the code to client-side only.
For more information on error handling in Next.js, you can refer to the [Next.js Error Handling documentation](<https://nextjs.org/docs/pages/building-your-application/configuring>
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@little palm kapa.ai is still learning and improving, please let us know how it did by reacting below
If I have useState I have to write "use client" on top of the page, and I don't want that
@upbeat storm
If I have useState I have to write "use client" on top of the page, and I don't want that
Let me check the knowledge base for you. One moment! :books:
If you want to use useState but avoid adding "use client" at the top of your page, you can isolate the client-side logic into a separate component. This way, you can keep your main page as a server component and only mark the specific parts that need to be client-side.
Here's how you can achieve this:
- Create a separate client component for the form.
- Use the
"use client"directive in that component. - Import and use this client component in your main page.
Step 1: Create a Client Component
Create a new file, e.g., ClientLoginForm.tsx, and move the form logic there:
// ClientLoginForm.tsx
'use client';
import { useState } from 'react';
import { Button, Form, Input, message } from "antd";
import { toUpperCase } from "../../utils";
import FormItem from "antd/lib/form/FormItem";
import InputPassword from "antd/lib/input/Password";
import { Icons } from "../Icons";
interface LoginFormValues {
email: string;
password: string;
}
const ClientLoginForm = ({ login }) => {
const [error, setError] = useState(null);
const handleSubmit = async (values: LoginFormValues) => {
try {
await login(values);
} catch (err) {
setError(err.message);
}
};
return (
<>
{error && <div className="error">{error}</div>}
<Form onFinish={handleSubmit} size="large">
<FormItem
name="email"
rules={[
{ required: true, message: "ელ.ფოსტა აუცილებელია!", type: "email" },
]}
>
<Input placeholder={toUpperCase("ელ.ფოსტა")} />
</FormItem>
<FormItem
name="password"
rules={[{ required: true, message: "პაროლი აუცილებელია!" }]}
>
<InputPassword placeholder={toUpperCase("პაროლი")} autoComplete="on" />
</FormItem>
<Button type="primary" htmlType="submit" icon={<Icons.sendIcon />}>
{toUpperCase("გაგზავნა")}
</Button>
</Form>
</>
);
};
export default ClientLoginForm;
### Step 2: Use the Client Component in Your Main Page
Modify your main page to import and use the `ClientLoginForm` component:
```javascript
// main page file (e.g., page.tsx)
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import ClientLoginForm from './ClientLoginForm';
interface LoginFormValues {
email: string;
password: string;
}
const LoginForm = () => {
const login = async (values: LoginFormValues) => {
"use server";
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/auth/login`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
}
);
if (!response.ok) {
throw new Error("ელ.ფოსტა ან პაროლი არასწორია!");
}
const data = await response.json();
cookies().set("accessToken", JSON.stringify(data.accessToken));
cookies().set("refreshToken", JSON.stringify(data.refreshToken));
cookies().set("user", JSON.stringify(data.user));
redirect("/");
};
return <ClientLoginForm login={login} />;
};
export default LoginForm;