react-form-hook的reset()问题

问题描述 投票:0回答:1

我使用react-hook-form创建了一个表单。我已经使用 zustand 将表单详细信息存储为本地存储中的缓存,这样,如果用户想要从之前填写的表单中填写表单的详细信息。

功能性

  • 当我填写详细信息、提交并将表单详细信息存储在缓存(zustand store)中时,所有表单字段都应该清空。
  • 如果我单击从缓存/先前表单详细信息导入数据,则应填写缓存中的详细信息。

问题

通常,当我填写详细信息并提交表单时,我会被提交并且所有字段都会被清除。 但是当我从缓存导入数据并提交表单时,表单正在提交,但表单字段没有被清除。我无法弄清楚为什么会发生这种情况。

代码

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;
reactjs forms react-hook-form
1个回答
0
投票

原因

在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]);
© www.soinside.com 2019 - 2024. All rights reserved.