I have created a form using react-hook-form. I have used zustand for storing form details as a cache in local storage, so that if the user wants to fill in details of the form from a previously filled form.
Normally when I filling my details and submit my form I get submitted and all fields are cleared. But when I import data from the cache and submit form then form is getting submitted but the form fields are not getting cleared. I am unable to figure out why this is happening.
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;
Its not mentioned in reset() documentation of react-hook-form, that if somehow we are providing/setting field values through reset at starting then reset() function considers that value as default value.
When data was filled with cache at starting with help of reset(), then reset considered it as default value of fields and at the time of submission of form reset() was called, so it populated all the fields with same value as submitted recently.
Just need to provide whole object as key value with empty values while reseting form after submission.
useEffect(() => {
if (isSubmitSuccessful) {
console.log('clearing form');
reset({
'application-deadline': '',
'company-name': '',
email: '',
'job-description': '',
'job-title': '',
jobType: '',
location: '',
'phone-number': '',
salary: '',
});
}
}, [isSubmitSuccessful]);