React Hook Form
Маягт (form) бол вэб аппын хамгийн нийтлэг хэсэг — нэвтрэх, бүртгүүлэх, захиалга өгөх гэх мэт. React-д маягт гараар зохицуулах нь их код шаарддаг. React Hook Form нь validation, error message, submit логик зэрэг бүхнийг хэд дахин хялбар болгодог хамгийн алдартай library. Эхлэхэд хялбар, дэвшилтэт хэрэглээ ч байдаг!
Суулгах
npm install react-hook-form
Үндсэн хэрэглээ
useForm hook нь маягтын бүх логикийг агуулдаг:
import { useForm } from "react-hook-form";
function LoginForm() {
const {
register, // input-уудыг бүртгэх
handleSubmit, // submit зохицуулах
formState: { errors, isSubmitting }, // validation алдаа, submit байдал
} = useForm();
async function onSubmit(data) {
// data нь { email: "...", password: "..." } байна
console.log("Нэвтрэх мэдээлэл:", data);
await new Promise((r) => setTimeout(r, 1000)); // API дуудах дуурайлт
}
return (
<form
onSubmit={handleSubmit(onSubmit)}
style={{
display: "flex",
flexDirection: "column",
gap: "16px",
maxWidth: "360px",
}}
>
<div>
<label>И-мэйл</label>
<input
type="email"
// register нь validation дүрмүүдийг тодорхойлно
{...register("email", {
required: "И-мэйл оруулна уу",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Зөв и-мэйл хаяг оруулна уу",
},
})}
style={{
border: errors.email ? "1px solid red" : "1px solid #ccc",
padding: "8px",
width: "100%",
}}
/>
{/* Validation алдаа */}
{errors.email && (
<p style={{ color: "red", fontSize: "14px" }}>
{errors.email.message}
</p>
)}
</div>
<div>
<label>Нууц үг</label>
<input
type="password"
{...register("password", {
required: "Нууц үг оруулна уу",
minLength: {
value: 8,
message: "Нууц үг 8-аас дээш тэмдэгт байх ёстой",
},
})}
style={{
border: errors.password ? "1px solid red" : "1px solid #ccc",
padding: "8px",
width: "100%",
}}
/>
{errors.password && (
<p style={{ color: "red", fontSize: "14px" }}>
{errors.password.message}
</p>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Нэвтэрч байна..." : "Нэвтрэх"}
</button>
</form>
);
}
register("email", { ... }) нь input-г маягтад бүртгэж, validation дүрмүүдийг тохируулна. handleSubmit нь validation амжилттай болсны дараа л onSubmit-ийг дуудна.
Бүртгэлийн маягт — дэлгэрэнгүй validation
import { useForm } from "react-hook-form";
function RegisterForm() {
const {
register,
handleSubmit,
watch, // талбарын утгыг ажиглах
formState: { errors, isSubmitting, isSubmitSuccessful },
} = useForm({ mode: "onBlur" }); // talbar-аас гарахад validation ажиллана
// password талбарын утгыг ажигладаг — confirm-тэй харьцуулахад хэрэгтэй
const password = watch("password");
async function onSubmit(data) {
await fetch("/api/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
}
if (isSubmitSuccessful) {
return <p style={{ color: "green" }}>Бүртгэл амжилттай боллоо! 🎉</p>;
}
return (
<form
onSubmit={handleSubmit(onSubmit)}
style={{
display: "flex",
flexDirection: "column",
gap: "12px",
maxWidth: "400px",
}}
>
<div>
<label>Нэр</label>
<input
{...register("name", {
required: "Нэр оруулна уу",
minLength: {
value: 2,
message: "Нэр 2-оос дээш тэмдэгт байх ёстой",
},
})}
/>
{errors.name && <p style={{ color: "red" }}>{errors.name.message}</p>}
</div>
<div>
<label>И-мэйл</label>
<input
type="email"
{...register("email", {
required: "И-мэйл оруулна уу",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Буруу и-мэйл хаяг",
},
})}
/>
{errors.email && <p style={{ color: "red" }}>{errors.email.message}</p>}
</div>
<div>
<label>Нууц үг</label>
<input
type="password"
{...register("password", {
required: "Нууц үг оруулна уу",
minLength: { value: 8, message: "8-аас дээш тэмдэгт байх ёстой" },
})}
/>
{errors.password && (
<p style={{ color: "red" }}>{errors.password.message}</p>
)}
</div>
<div>
<label>Нууц үг давтах</label>
<input
type="password"
{...register("confirmPassword", {
required: "Нууц үгийг давтана уу",
validate: (value) =>
value === password || "Нууц үг таарахгүй байна",
})}
/>
{errors.confirmPassword && (
<p style={{ color: "red" }}>{errors.confirmPassword.message}</p>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Бүртгүүлж байна..." : "Бүртгүүлэх"}
</button>
</form>
);
}
validate функц нь custom validation дүрэм — утга буцаавал тухайн утга нь алдааны мэдэгдэл болно, true буцаавал validation амжилтай гэсэн үг.
useFormState ба нарийн тохиргоо
import { useForm, Controller } from "react-hook-form";
// Controller нь custom input component-уудтай ажиллахад хэрэгтэй
function AdvancedForm() {
const {
register,
handleSubmit,
control, // Controller-д дамжуулна
reset, // маягтыг анхны утганд нь буцаах
setValue, // программаар утга тавих
formState: { errors, isDirty, isValid },
} = useForm({
defaultValues: {
name: "",
role: "student",
},
mode: "onChange", // бичих болгонд validation
});
function onSubmit(data) {
console.log(data);
reset(); // submit-н дараа маягтыг цэвэрлэнэ
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name", { required: "Нэр шаардлагатай" })} />
{errors.name && <p style={{ color: "red" }}>{errors.name.message}</p>}
<select {...register("role")}>
<option value="student">Суралцагч</option>
<option value="teacher">Багш</option>
<option value="admin">Админ</option>
</select>
{/* isDirty — маягт өөрчлөгдсөн эсэх */}
{/* isValid — бүх validation давсан эсэх */}
<button type="submit" disabled={!isDirty || !isValid}>
Хадгалах
</button>
</form>
);
}
isDirty ба isValid ашиглан submit товчийг зохистой идэвхтэй/идэвхгүй болгож болно — хэрэглэгч юу ч өөрчлөөгүй эсвэл validation алдаатай үед товч disabled байна.
Дараагийн хичээлд:
Zustand сурна — React-н хялбар бөгөөд хүчирхэг глобал state management library. Redux-аас хавьгүй хялбар, Context-ээс илүү хурдан. Нэг файлд бүх глобал state-г зохион байгуулж чаддаг.