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.
Functionality
- All form fields should be emptied when I fill in the details, submit them, and store the form details in the cache(zustand store).
- If I click on import data from cache/previous form details then details from cache should be filled in.
Issue
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.
Code
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;