#How can I show the error on client side when I have full server component?

1 messages · Page 1 of 1 (latest)

solemn gullBOT
#

Hi @uneven burrow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

In your current setup, you are throwing an error in the server component when the response is not okay. However, this error is not being caught and handled on the client side.

To show the error on the client side, you can use React's state to handle the error message. Here is an example from the Next.js documentation:

import React, { useState, FormEvent } from 'react'
 
export default function Page() {
 const [isLoading, setIsLoading] = useState<boolean>(false)
 const [error, setError] = useState<string | null>(null)
 
 async function onSubmit(event: FormEvent<HTMLFormElement>) {
 event.preventDefault()
 setIsLoading(true)
 setError(null) // Clear previous errors when a new request starts
 
 try {
 const formData = new FormData(event.currentTarget)
 const response = await fetch('/api/submit', {
 method: 'POST',
 body: formData,
 })
 
 if (!response.ok) {
 throw new Error('Failed to submit the data. Please try again.')
 }
 
 // Handle response if necessary
 const data = await response.json()
 // ...
 } catch (error) {
 // Capture the error message to display to the user
 setError(error.message)
 console.error(error)
 } finally {
 setIsLoading(false)
 }
 }
 
 return (
 <div>
 {error && <div style={{ color: 'red' }}>{error}</div>}
 <form onSubmit={onSubmit}>
 <input type="text" name="name" />
 <button type="submit" disabled={isLoading}>
 {isLoading ? 'Loading...' : 'Submit'}
 </button>
 </form>
 </div>
 )
}

In this example, an error state is initialized with useState. When the form is submitted, the error state is cleared. If an error occurs during the fetch request, the error message is set in the error state. This error message is then displayed in the form.

You can adapt this example to your needs. For instance, you can replace the fetch URL with your login API endpoint, and the form data with your login form data.

uneven burrow
#

@solemn gull I don't want to make the whole component as a client one

solemn gullBOT
#

Let me check the knowledge base for you. One moment! :books:

#

If you want to keep the component as a server component but handle errors on the client side, you can use a hybrid approach. You can use a client component to handle the form submission and error handling, while the rest of the component remains a server component.

Here's an example of how you can modify your LoginForm component to handle errors on the client side:

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";

const LoginForm = () => {
  const [error, setError] = useState(null);

  const login = async (values) => {
    "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) {
      setError("ელ.ფოსტა ან პაროლი არასწორია!");
      return;
    }

    redirect("/");
  };

  return (
    <Form onFinish={login} size="large">
      {error && <div>{error}</div>}
      <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>
<Link
href="/reset-password"
className="text-xs text-secondary text-opacity-50 hover:text-opacity-80 hover:text-secondary mb-2 block"
>
{toUpperCase("პაროლის")}{" "}
<span className="text-primary underline">{toUpperCase("აღდგენა")}</span>
</Link>
<Button type="primary" htmlType="submit" icon={<Icons.sendIcon />}>
{toUpperCase("გაგზავნა")}
</Button>
</Form>
);
};

export default LoginForm;


In this example, I've added a `useState` hook to manage the error state. When the response from the fetch request is not okay, I set the error state to the error message. This error message is then displayed in the form.

Please note that this is a simplified example and you might need to adjust it according to your needs.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------