I'm using react-hook-form, and I'm wondering if it's possible to create a component that is passing the form errors using react-hook-form.
I have the following component
import { useForm } from "react-hook-form";
import { XIcon } from "@heroicons/react/outline";
export default function ErrorsPopup() {
const {
formState: { errors },
} = useForm({
criteriaMode: "all",
});
return (
<>
{Object.keys(errors).length > 0 && (
<div className="mt-6 text-white bg-red-600 border-4 border-red-700 alert-start">
<div className="flex justify-between items-center bg-red-700 py-2 px-4">
<div>
<p>The following errors have occurred:</p>
</div>
<div className="cursor-pointer">
<XIcon className="h-6 w-6 text-white alert-close" />
</div>
</div>
<div className="py-2 px-4">
<div className="flex flex-col gap-2">
{Object.entries(errors).map(([index, error]) => (
<div className="flex flex-col gap-y-6 sm:gap-x-8" key={index}>
<p>• {error.message}</p>
</div>
))}
</div>
</div>
</div>
)}
</>
);
}
and I have added this to the following page
import { useState } from "react";
import Head from "next/head";
import Link from "next/link";
import Image from "next/image";
import Background from "../../../public/images/option1.png";
import Router from "next/router";
import { signIn } from "next-auth/client";
import { useForm } from "react-hook-form";
import { SaveIcon } from "@heroicons/react/outline";
import ErrorsPopup from "../../components/ErrorsPopup";
export default function Login() {
const { register, handleSubmit } = useForm();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const onSubmit = async () => {
await signIn("credentials", {
redirect: false,
email: email,
password: password,
});
Router.push("/dashboard");
};
return (
<>
<Head>
<title>Ellis Development - Login</title>
</Head>
<div className="relative">
<div className="md:flex">
{/* Image */}
<div className="flex items-center justify-center bg-blue-700 h-screen lg:w-96">
<Image src={Background} width={350} height={350} layout="fixed" />
</div>
{/* Contact form */}
<div className="flex flex-col justify-center py-10 px-6 sm:px-10 w-full">
<h1 className="text-4xl font-extrabold text-grey-800">Login</h1>
{/* errors */}
<ErrorsPopup />
<form
onSubmit={handleSubmit(onSubmit)}
className="mt-6 flex flex-col gap-y-6 sm:gap-x-8"
>
{/* email field */}
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-900"
>
Email
</label>
<div className="mt-1">
<input
{...register("email", { required: "E-mail is required" })}
type="text"
name="email"
id="email"
className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
onChange={(event) => setEmail(event.target.value)}
/>
</div>
</div>
{/* password field */}
<div>
<label
htmlFor="password"
className="block text-sm font-medium text-gray-900"
>
Password
</label>
<div className="mt-1">
<input
{...register("password", {
required: "Password is required",
})}
type="password"
name="password"
id="password"
className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
onChange={(event) => setPassword(event.target.value)}
/>
</div>
</div>
<div className="flex items-center justify-between sm:col-span-2">
<div>
<button
type="submit"
className="mt-2 mr-2 w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-blue-700 hover:bg-blue-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 sm:w-auto"
>
<SaveIcon className="w-4 h-4 mr-4" />
Login
</button>
</div>
<div>
<Link href="/dashboard/auth/register">
<a className="underline decoration-blue-500 decoration-4 hover:decoration-2 mr-4">
Register
</a>
</Link>
<Link href="/dashboard/auth/forgot">
<a className="underline decoration-blue-500 decoration-4 hover:decoration-2">
Forgot your password?
</a>
</Link>
</div>
</div>
</form>
</div>
</div>
</div>
</>
);
}
So I'm trying to create a component for all forms where I can simply just show any errors to keep the code DRY, but the component is not showing up.
Sure I'm missing something silly but I'm new to react so any help would be create.
CodePudding user response:
You've have to use FormProvider
in your Login
component and useFormContext
in your ErrorPopup