react-form-hook useFieldArray 不在我的 nexjs 应用程序中显示表单

问题描述 投票:0回答:1
"use client";
import ButtonPrimary from "@/shared/ButtonPrimary";
import ButtonSecondary from "@/shared/ButtonSecondary";
import React, { FC, useState } from "react";
import { Controller, useFieldArray } from "react-hook-form";
import Image from "next/image";
import Checkbox from "@/shared/Checkbox";
import FormItem from "./FormItem";
import Input from "@/shared/Input";

export interface PageAddListing7Props {
  formData: any[];
  errors: any;
  control: any;
  register: any;
  handleSubmit: any;
  prevPageHandler: any;
  nextPageHandler: any;
  setFormData: any;
  watch: any;
  setError: any;
  coverImgee: any;
  setCoverImage: any;
  image1: any;
  image2: any;
  image3: any;
  image4: any;
  setImage1: any;
  setImage2: any;
  setImage3: any;
  setImage4: any;
  data2: any;
}

const PageAddListing7: FC<PageAddListing7Props> = ({
  formData,
  errors,
  control,
  register,
  handleSubmit,
  prevPageHandler,
  nextPageHandler,
  setFormData,
  watch,
  setError,
  coverImgee,
  setCoverImage,
  image1,
  image2,
  image3,
  image4,
  setImage4,
  setImage1,
  setImage2,
  setImage3,
  data2,
}) => {
  const [multipleCategory, setMultipleCategory] = useState(false);
  const { fields, append, remove } = useFieldArray({
    control,
    name: "entries",
  });

  console.log("fields")
  return (
    <>
      <div className="w-14 border-b border-neutral-200 dark:border-neutral-700"></div>
      {/* FORM */}
      <form
        className="space-y-8"
        onSubmit={handleSubmit((data: any) => {
          setFormData({ ...formData, ...data });
          nextPageHandler();
        })}
      >
        {multipleCategory ? null : (
          <div>
            <div>
              <h2 className="text-2xl font-semibold">Pictures of the hall</h2>
              <span className="block mt-2 text-neutral-500 dark:text-neutral-400">
                A few beautiful photos will help customers have more sympathy
                for your hall.
              </span>
            </div>

            <div>
              <span className="text-lg font-semibold">Cover image</span>
              <div className="mt-5 ">
                <div className="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-neutral-300 dark:border-neutral-6000 border-dashed rounded-md">
                  <div className="space-y-1 text-center">
                    {coverImgee ? (
                      <Image
                        src={URL.createObjectURL(coverImgee)}
                        alt="image"
                        className="object-cover"
                        width={200}
                        height={200}
                      />
                    ) : (
                      <svg
                        className="mx-auto h-12 w-12 text-neutral-400"
                        stroke="currentColor"
                        fill="none"
                        viewBox="0 0 48 48"
                        aria-hidden="true"
                      >
                        <path
                          d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        ></path>
                      </svg>
                    )}
                    <div className="flex text-sm text-neutral-6000 dark:text-neutral-300">
                      <label
                        htmlFor="file-upload"
                        className="relative cursor-pointer  rounded-md font-medium text-primary-6000 hover:text-primary-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-primary-500"
                      >
                        <Controller
                          name="image_0"
                          control={control}
                          rules={{ required: "Please select a cover image." }}
                          render={({ field }) => (
                            <label
                              htmlFor="fileInput"
                              className="cursor-pointer bg-transparent border-none outline-none focus:outline-none"
                            >
                              <span className="">Upload a file</span>
                              <input
                                type="file"
                                id="fileInput"
                                onChange={(e: any) => {
                                  const selectedFile = e.target.files[0];
                                  if (selectedFile && selectedFile.size > 0) {
                                    data2.append("image[0]", selectedFile);
                                    console.log("settt");
                                  } else {
                                    // Handle the case when no file is selected or the file is empty
                                    setError(
                                      "image_0",
                                      "Please select a valid file."
                                    );
                                  }
                                  field.onChange(selectedFile);
                                  setCoverImage(e.target.files[0]);
                                }}
                                className="w-full absolute h-full opacity-0 cursor-pointer"
                              />
                            </label>
                          )}
                        />
                      </label>
                      <p className="pl-1">or drag and drop</p>
                    </div>
                    <p className="text-xs text-neutral-500 dark:text-neutral-400">
                      PNG, JPG, GIF up to 10MB
                    </p>
                  </div>
                </div>
              </div>
              <span className="text-red-500 text-sm mt-2">
                {errors["image_0"] && errors["image_0"].message}
              </span>
            </div>

            <div>
              <span className="text-lg font-semibold">Picture one</span>
              <div className="mt-5 ">
                <div className="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-neutral-300 dark:border-neutral-6000 border-dashed rounded-md">
                  <div className="space-y-1 text-center">
                    {image1 ? (
                      <Image
                        src={URL.createObjectURL(image1)}
                        alt="image"
                        className="object-cover"
                        width={200}
                        height={200}
                      />
                    ) : (
                      <svg
                        className="mx-auto h-12 w-12 text-neutral-400"
                        stroke="currentColor"
                        fill="none"
                        viewBox="0 0 48 48"
                        aria-hidden="true"
                      >
                        <path
                          d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        ></path>
                      </svg>
                    )}
                    <div className="flex text-sm text-neutral-6000 dark:text-neutral-300">
                      <label
                        htmlFor="file-upload"
                        className="relative cursor-pointer  rounded-md font-medium text-primary-6000 hover:text-primary-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-primary-500"
                      >
                        <Controller
                          name="image_1"
                          control={control}
                          rules={{ required: "Please select an image." }}
                          render={({ field }) => (
                            <label
                              htmlFor="image_1"
                              className="cursor-pointer bg-transparent border-none outline-none focus:outline-none"
                            >
                              <span className="">Upload a file</span>
                              <input
                                type="file"
                                id="image_1"
                                onChange={(e: any) => {
                                  const selectedFile = e.target.files[0];
                                  field.onChange(selectedFile);
                                  setImage1(e.target.files[0]);
                                }}
                                className="w-full absolute h-full opacity-0 cursor-pointer"
                              />
                            </label>
                          )}
                        />
                      </label>
                      <p className="pl-1">or drag and drop</p>
                    </div>
                    <p className="text-xs text-neutral-500 dark:text-neutral-400">
                      PNG, JPG, GIF up to 10MB
                    </p>
                  </div>
                </div>
              </div>
              <span className="text-red-500 text-sm mt-2">
                {errors["image_1"] && errors["image_1"].message}
              </span>
            </div>
            <div>
              <span className="text-lg font-semibold">Picture two</span>
              <div className="mt-5 ">
                <div className="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-neutral-300 dark:border-neutral-6000 border-dashed rounded-md">
                  <div className="space-y-1 text-center">
                    {image2 ? (
                      <Image
                        src={URL.createObjectURL(image2)}
                        alt="image"
                        className="object-cover"
                        width={200}
                        height={200}
                      />
                    ) : (
                      <svg
                        className="mx-auto h-12 w-12 text-neutral-400"
                        stroke="currentColor"
                        fill="none"
                        viewBox="0 0 48 48"
                        aria-hidden="true"
                      >
                        <path
                          d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        ></path>
                      </svg>
                    )}
                    <div className="flex text-sm text-neutral-6000 dark:text-neutral-300">
                      <label
                        htmlFor="image_2"
                        className="relative cursor-pointer  rounded-md font-medium text-primary-6000 hover:text-primary-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-primary-500"
                      >
                        <Controller
                          name="image_2"
                          control={control}
                          rules={{ required: "Please select an image." }}
                          render={({ field }) => (
                            <label
                              htmlFor="image_2"
                              className="cursor-pointer bg-transparent border-none outline-none focus:outline-none"
                            >
                              <span className="">Upload a file</span>
                              <input
                                type="file"
                                id="image_2"
                                onChange={(e: any) => {
                                  const selectedFile = e.target.files[0];
                                  field.onChange(selectedFile);
                                  setImage2(e.target.files[0]);
                                }}
                                className="w-full absolute h-full opacity-0 cursor-pointer"
                              />
                            </label>
                          )}
                        />
                      </label>
                      <p className="pl-1">or drag and drop</p>
                    </div>
                    <p className="text-xs text-neutral-500 dark:text-neutral-400">
                      PNG, JPG, GIF up to 10MB
                    </p>
                  </div>
                </div>
              </div>
              <span className="text-red-500 text-sm mt-2">
                {errors["image_2"] && errors["image_2"].message}
              </span>
            </div>
            <div>
              <span className="text-lg font-semibold">Picture three</span>
              <div className="mt-5 ">
                <div className="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-neutral-300 dark:border-neutral-6000 border-dashed rounded-md">
                  <div className="space-y-1 text-center">
                    {image3 ? (
                      <Image
                        src={URL.createObjectURL(image3)}
                        alt="image"
                        className="object-cover"
                        width={200}
                        height={200}
                      />
                    ) : (
                      <svg
                        className="mx-auto h-12 w-12 text-neutral-400"
                        stroke="currentColor"
                        fill="none"
                        viewBox="0 0 48 48"
                        aria-hidden="true"
                      >
                        <path
                          d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        ></path>
                      </svg>
                    )}
                    <div className="flex text-sm text-neutral-6000 dark:text-neutral-300">
                      <label
                        htmlFor="image_2"
                        className="relative cursor-pointer  rounded-md font-medium text-primary-6000 hover:text-primary-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-primary-500"
                      >
                        <Controller
                          name="image_3"
                          control={control}
                          rules={{ required: "Please select an image." }}
                          render={({ field }) => (
                            <label
                              htmlFor="image_3"
                              className="cursor-pointer bg-transparent border-none outline-none focus:outline-none"
                            >
                              <span className="">Upload a file</span>
                              <input
                                type="file"
                                id="image_3"
                                onChange={(e: any) => {
                                  const selectedFile = e.target.files[0];
                                  field.onChange(selectedFile);
                                  setImage3(e.target.files[0]);
                                }}
                                className="w-full absolute h-full opacity-0 cursor-pointer"
                              />
                            </label>
                          )}
                        />
                      </label>
                      <p className="pl-1">or drag and drop</p>
                    </div>
                    <p className="text-xs text-neutral-500 dark:text-neutral-400">
                      PNG, JPG, GIF up to 10MB
                    </p>
                  </div>
                </div>
              </div>
              <span className="text-red-500 text-sm mt-2">
                {errors["image_3"] && errors["image_3"].message}
              </span>
            </div>
            <div>
              <span className="text-lg font-semibold">Picture four</span>
              <div className="mt-5 ">
                <div className="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-neutral-300 dark:border-neutral-6000 border-dashed rounded-md">
                  <div className="space-y-1 text-center">
                    {image4 ? (
                      <Image
                        src={URL.createObjectURL(image4)}
                        alt="image"
                        className="object-cover"
                        width={200}
                        height={200}
                      />
                    ) : (
                      <svg
                        className="mx-auto h-12 w-12 text-neutral-400"
                        stroke="currentColor"
                        fill="none"
                        viewBox="0 0 48 48"
                        aria-hidden="true"
                      >
                        <path
                          d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        ></path>
                      </svg>
                    )}
                    <div className="flex text-sm text-neutral-6000 dark:text-neutral-300">
                      <label
                        htmlFor="image_4"
                        className="relative cursor-pointer rounded-md font-medium text-primary-6000 hover:text-primary-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-primary-500"
                      >
                        <Controller
                          name="image_4"
                          control={control}
                          rules={{ required: "Please select an image." }}
                          render={({ field }) => (
                            <label
                              htmlFor="image_4"
                              className="cursor-pointer bg-transparent border-none outline-none focus:outline-none"
                            >
                              <span className="">Upload a file</span>
                              <input
                                type="file"
                                id="image_4"
                                onChange={(e: any) => {
                                  const selectedFile = e.target.files[0];
                                  field.onChange(selectedFile);
                                  setImage4(e.target.files[0]);
                                }}
                                className="w-full absolute h-full opacity-0 cursor-pointer"
                              />
                            </label>
                          )}
                        />
                      </label>
                      <p className="pl-1">or drag and drop</p>
                    </div>
                    <p className="text-xs text-neutral-500 dark:text-neutral-400">
                      PNG, JPG, GIF up to 10MB
                    </p>
                  </div>
                </div>
              </div>
              <span className="text-red-500 text-sm mt-2">
                {errors["image_4"] && errors["image_4"].message}
              </span>
            </div>
          </div>
        )}

        {/* ----------------- */}

        <div className="mt-6 flex flex">
          <Checkbox
            label="Check if you have more than one category for this hall"
            name="mutiple-halls"
            onChange={() => setMultipleCategory((prevState) => !prevState)}
            defaultChecked={false}
          />
        </div>

 /* this display on my browser*/
        <p>{multipleCategory}</p>
        {multipleCategory ? (
          <div className="space-y-8  border rounded p-4">
            {/* ITEM */}

            <FormItem label="Size (Acreage (m2))" desc="How large the hall is">
              <Input
                placeholder="..."
                type="number"
                {...register("size", {
                  required: {
                    value: true,
                    message: "size is required", // Set your custom error message
                  },
                })}
              />
              {errors?.size && (
                <p className="text-red-500 text-sm mt-1">
                  {`${errors?.size?.message}`}
                </p>
              )}
            </FormItem>

            <FormItem
              label="Seat capacity"
              desc="The number of seats the hall has"
            >
              <Input
                placeholder="100"
                type="number"
                {...register("seat_capacity", {
                  required: {
                    value: true,
                    message: "size is required", // Set your custom error message
                  },
                })}
              />
              {errors?.seat_capacity && (
                <p className="text-red-500 text-sm mt-1">
                  {`${errors?.seat_capacity?.message}`}
                </p>
              )}
            </FormItem>

            <FormItem label="Amount " desc="What the cost of the hall is">
              <Input
                placeholder="..."
                type="number"
                {...register("amount", {
                  required: {
                    value: true,
                    message: "amount is required", // Set your custom error message
                  },
                })}
              />
              {errors?.size && (
                <p className="text-red-500 text-sm mt-1">
                  {`${errors?.size?.message}`}
                </p>
              )}
            </FormItem>

            <div className="flex justify-end space-x-5">
              <ButtonPrimary type="submit">{"Add Row"}</ButtonPrimary>
            </div>
          </div>
        ) : null}


         /* this does not display on my browser*/
        {multipleCategory?
          fields.map((item, index) => (
            <div key={item.id}>
              {/* Your form fields for each entry */}
              <FormItem
                label={`Size (Acreage (m2)) for Entry ${index + 1}`}
                desc="How large the hall is"
              >
                <Input
                  placeholder="..."
                  type="number"
                  {...control.fields[index].size}
                />
              </FormItem>

              <FormItem
                label={`Seat capacity for Entry ${index + 1}`}
                desc="The number of seats the hall has"
              >
                <Input
                  placeholder="100"
                  type="number"
                  {...control.fields[index].seat_capacity}
                />
              </FormItem>

              <FormItem
                label={`Amount for Entry ${index + 1}`}
                desc="What the cost of the hall is"
              >
                <Input
                  placeholder="..."
                  type="number"
                  {...control.fields[index].amount}
                />
              </FormItem>

              <div className="flex justify-end space-x-5">
                {index === fields.length - 1 && (
                  <ButtonPrimary type="button" onClick={() => append({})}>
                    Add Row
                  </ButtonPrimary>
                )}
                {index > 0 && (
                  <ButtonSecondary type="button" onClick={() => remove(index)}>
                    Remove Row
                  </ButtonSecondary>
                )}
              </div>
            </div>
          )): null}

        {/* ----------------- */}

        <div className="flex justify-end space-x-5">
          <ButtonSecondary type="button" onClick={prevPageHandler}>
            Go back
          </ButtonSecondary>
          <ButtonPrimary type="submit">{"Continue"}</ButtonPrimary>
        </div>
      </form>
    </>
  );
};

export default PageAddListing7;

我想要实现的是,当我单击添加行时,它应该克隆表单以允许用户输入多个条目,第一部分是我不使用 useFieldArray 的表单的第一部分显示在我的 nexjs 应用程序上,但是为了改进它,我决定使用 useFieldArray 来允许用户添加行并创建更多条目。代码块不会显示在浏览器中。有人在使用 nextjs 时遇到过类似的问题吗?

我需要帮助,但我没有收到任何错误。

reactjs
1个回答
0
投票

从最初的外观来看,您的代码似乎是正确的,但它可能与复选框组件有关:

您可以尝试最初将 multipleCategories 设置为 true 进行调试吗?如果仍然不起作用,请尝试添加使用效果并观察 fields 属性、控制台日志以确保其工作;下一步是删除 multipleCategory 检查并确保它不会导致错误。

© www.soinside.com 2019 - 2024. All rights reserved.