使用 react-hook-form 为表单错误创建组件
create component for form errors using react-hook-form
我正在使用 react-hook-form,我想知道是否可以使用 react-hook-form 创建一个传递表单错误的组件。
我有以下组件
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>
)}
</>
);
}
我已将其添加到下一页
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>
</>
);
}
所以我正在尝试为所有表单创建一个组件,我可以在其中简单地显示任何错误以保持代码干燥,但该组件没有显示。
当然,我遗漏了一些愚蠢的东西,但我是新手,所以可以提供任何帮助。
我认为您需要在 ErrorsPopup 组件中使用 useFormContext
而不是 useForm
您必须在 Login
组件中使用 FormProvider
并在 ErrorPopup
中使用 useFormContext
https://react-hook-form.com/api/useformcontext
我添加了评论 //
我所做的更改。
Login.js
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, FormProvider } from "react-hook-form"; //
import { SaveIcon } from "@heroicons/react/outline";
import ErrorsPopup from "../../components/ErrorsPopup";
export default function Login() {
const methods = useForm(); //
const { register, handleSubmit } = methods; //
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>
<FormProvider {...methods}> //
{/* 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>
</FormProvider> //
</div>
</div>
</div>
</>
);
}
ErrorPopup.js
import { useFormContext } from "react-hook-form"; //
import { XIcon } from "@heroicons/react/outline";
export default function ErrorsPopup() {
const {
formState: { errors },
} = useFormContext({ //
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>
)}
</>
);
}
我正在使用 react-hook-form,我想知道是否可以使用 react-hook-form 创建一个传递表单错误的组件。
我有以下组件
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>
)}
</>
);
}
我已将其添加到下一页
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>
</>
);
}
所以我正在尝试为所有表单创建一个组件,我可以在其中简单地显示任何错误以保持代码干燥,但该组件没有显示。
当然,我遗漏了一些愚蠢的东西,但我是新手,所以可以提供任何帮助。
我认为您需要在 ErrorsPopup 组件中使用 useFormContext
而不是 useForm
您必须在 Login
组件中使用 FormProvider
并在 ErrorPopup
useFormContext
https://react-hook-form.com/api/useformcontext
我添加了评论 //
我所做的更改。
Login.js
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, FormProvider } from "react-hook-form"; //
import { SaveIcon } from "@heroicons/react/outline";
import ErrorsPopup from "../../components/ErrorsPopup";
export default function Login() {
const methods = useForm(); //
const { register, handleSubmit } = methods; //
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>
<FormProvider {...methods}> //
{/* 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>
</FormProvider> //
</div>
</div>
</div>
</>
);
}
ErrorPopup.js
import { useFormContext } from "react-hook-form"; //
import { XIcon } from "@heroicons/react/outline";
export default function ErrorsPopup() {
const {
formState: { errors },
} = useFormContext({ //
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>
)}
</>
);
}