我使用react-hook-form创建了一个表单。我已经使用 zustand 将表单详细信息存储为本地存储中的缓存,这样,如果用户想要从之前填写的表单中填写表单的详细信息。
通常,当我填写详细信息并提交表单时,我会被提交并且所有字段都会被清除。 但是当我从缓存导入数据并提交表单时,表单正在提交,但表单字段没有被清除。我无法弄清楚为什么会发生这种情况。
import React, { useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { DatePicker } from '@/components/date-picker';
import { RiLoader5Fill } from 'react-icons/ri';
import { useJobPostCache } from '@/store/jobpost-cache';
//shadcn UI imports
import { Textarea } from '@/components/ui/textarea';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
/**
*
* @description This is a form to post a job. It uses the react-hook-form library for form validation.
*/
function JobPost() {
const {
formState: { errors, isSubmitting, isSubmitSuccessful },
register,
handleSubmit,
control,
reset,
} = useForm();
const { jobPostCache, setJobPostCache, clearJobPostCache } =
useJobPostCache();
const formSumbimission = async (data) => {
setJobPostCache(data);
await new Promise((resolve) => setTimeout(resolve, 2000));
};
const importFormDataFromCache = () => {
console.log('importing data from cache');
reset(jobPostCache);
};
useEffect(() => {
if (isSubmitSuccessful) {
console.log('clearing form');
reset();
}
}, [isSubmitSuccessful]);
return (
<div>
<div className="max-w-[1300px] mx-auto min-h-screen px-3">
<h1 className="text-center text-2xl pt-10 font-semibold ">
Post your <span className="text-blue-500 font-semibold">JOB</span>!
</h1>
{
<p
className="text-sm text-right text-red-500 cursor-pointer"
onClick={importFormDataFromCache}
>
Import Data from previous Job post
</p>
}
<form
onSubmit={handleSubmit(formSumbimission)}
className="mx-auto max-w-[900px]"
>
<div className="block sm:flex gap-6">
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Job Title</h2>
<Input
type="text"
placeholder="Job Title"
{...register('job-title', {
required: 'Job title is required',
})}
/>
<span className="text-red-500 mt-2">
{errors['job-title'] && errors['job-title'].message}
</span>
</div>
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Company Name</h2>
<Input
type="text"
placeholder="Company Name"
{...register('company-name', {
required: 'Company Name is required',
})}
/>
<span className="text-red-500 mt-2">
{errors['company-name'] && errors['company-name'].message}
</span>
</div>
</div>
<div className="block sm:flex gap-6 ">
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Job Type</h2>
<Controller
name="jobType"
control={control}
rules={{ required: 'Please select job type' }}
render={({ field }) => (
<Select value={field.value} onValueChange={field.onChange}>
<SelectTrigger className="w-full">
<SelectValue placeholder="Job type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="full-time">Full Time</SelectItem>
<SelectItem value="part-time">Part Time</SelectItem>
<SelectItem value="internship">Internship</SelectItem>
</SelectContent>
</Select>
)}
/>
<span className="text-red-500 mt-2">
{errors['jobType'] && errors['jobType'].message}
</span>
</div>
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Location</h2>
<Input
type="text"
placeholder="Locatione"
{...register('location', {
required: 'Location is required',
})}
/>
<span className="text-red-500 mt-2">
{errors['location'] && errors['location'].message}
</span>
</div>
</div>
<div className="block sm:flex gap-6">
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Salary Range</h2>
<Input
type="text"
placeholder="Salary Range"
{...register('salary', {
required: 'Salary range is required',
})}
/>
<span className="text-red-500 mt-2">
{errors['salary'] && errors['salary'].message}
</span>
</div>
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Application Deadline</h2>
<div className="flex flex-col">
<Controller
name="application-deadline"
control={control}
rules={{ required: 'Please select application deadline' }}
render={({ field }) => (
<DatePicker
selected={field.value}
onChange={field.onChange}
/>
)}
/>
{errors['application-deadline'] && (
<span className="text-red-500 mt-2">
{errors['application-deadline'].message}
</span>
)}
</div>
</div>
</div>
<h2 className="font-semibold mt-7">Job Description</h2>
<Textarea
placeholder="Job Description"
{...register('job-description', {
required: 'Job description is required',
minLength: {
value: 30,
message: 'Job description must be atleast 30 characters',
},
})}
/>
<span className="text-red-500 mt-2">
{errors['job-description'] && errors['job-description'].message}
</span>
<div className="block sm:flex gap-6">
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Contact email</h2>
<Input
type="email"
placeholder="Contact email"
{...register('email', {
required: 'Please enter an email address',
validate: (value) => {
return (
/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(
value
) || 'Invalid email address'
);
},
})}
/>
<span className="text-red-500 mt-2">
{errors['email'] && errors['email'].message}
</span>
</div>
<div className="flex flex-col sm:w-1/2">
<h2 className="font-semibold mt-7">Contact Phone Number</h2>
<Input
type="tel"
placeholder="Contact phone number"
{...register('phone-number', {
minLength: {
value: 10,
message: 'Phone number must be atleast 10 digits',
},
maxLength: {
value: 10,
message: 'Phone number must not be more than 10 digits',
},
})}
/>
<span className="text-red-500 mt-2">
{errors['phone-number'] && errors['phone-number'].message}
</span>
</div>
</div>
<div className="flex justify-center items-center ">
<Button className="mt-7 w-full sm:w-36 mb-5">
{isSubmitting ? (
<div className="animate-spin text-3xl">
<RiLoader5Fill />
</div>
) : (
'Post Job'
)}
</Button>
</div>
</form>
</div>
</div>
);
}
export default JobPost;
在react-hook-form的reset()文档中没有提到,如果我们在启动时通过重置提供/设置字段值,那么reset()函数会将该值视为默认值。
当数据在reset()的帮助下开始填充缓存时,reset将其视为字段的默认值,并在提交表单时调用reset(),因此它使用与提交时相同的值填充所有字段最近。
只需提供整个对象作为键值,并在提交后重置表单时使用空值。
useEffect(() => {
if (isSubmitSuccessful) {
console.log('clearing form');
reset({
'application-deadline': '',
'company-name': '',
email: '',
'job-description': '',
'job-title': '',
jobType: '',
location: '',
'phone-number': '',
salary: '',
});
}
}, [isSubmitSuccessful]);