Nextjs Shadcn表单在单击时未提交

fkvaft9z  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(129)

我正在使用shadcn的react-hook-form,我已经设法导航文档以获得我需要的输入和选择,但是我创建的onSubmit函数没有做任何事情。
有人知道为什么吗?

"use client";

import * as z from "zod";
import { SubmitHandler, useForm, UseFormRegister } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Input } from "./ui/input";
import ErrorMessage from "./ErrorMessage";
import { Button } from "./ui/button";
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "./ui/Form";
import { Textarea } from "./ui/textarea";

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import toast from "react-hot-toast";

type ReminderFormSchemaType = z.infer<typeof reminderFormSchema>;

export const reminderFormSchema = z.object({
  title: z.string().min(1, { message: "Title required!" }),
  description: z.string().max(160),
  location: z.string(),
  recurring: z.boolean(),
  recurringDigit: z.string(),
  recurringString: z.string(),
  priority: z.string(),
});

const CreateReminder = () => {
  const form = useForm<ReminderFormSchemaType>({
    resolver: zodResolver(reminderFormSchema),
  });

  function onSubmit(data: ReminderFormSchemaType) {
    toast.success("success!");
  }

  return (
    <Form {...form}>
      <form
        onSubmit={form.handleSubmit(onSubmit)}
        className="flex flex-col w-full"
      >
        <FormField
          control={form.control}
          name="title"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Title</FormLabel>
              <FormControl>
                <Input placeholder="Create a title..." {...field} />
              </FormControl>
              <FormDescription>
                {form.formState.errors.title && (
                  <ErrorMessage
                    message={form.formState.errors.title?.message}
                  />
                )}
              </FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="description"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Description</FormLabel>
              <FormControl>
                <Textarea
                  placeholder="Type your description here..."
                  {...field}
                />
              </FormControl>
              <FormDescription></FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        <div className="flex flex-row justify-between items-center gap-x-3">
          <FormField
            control={form.control}
            name="recurringDigit"
            render={({ field }) => (
              <FormItem className="flex flex-row items-center gap-x-3">
                <FormLabel>Remind me every: </FormLabel>
                <Select onValueChange={field.onChange} defaultValue="1">
                  <FormControl>
                    <SelectTrigger className="w-[100px]">
                      <SelectValue placeholder="1" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent className="bg-lightbackground w-[100px]">
                    {Array.from(String(123456789)).map((value) => (
                      <SelectItem
                        key={value}
                        value={value}
                        className="cursor-pointer transition hover:bg-white hover:text-black"
                      >
                        {value}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </FormItem>
            )}
          />
          <div className="flex-1">
            <FormField
              control={form.control}
              name="recurringString"
              render={({ field }) => (
                <FormItem className="flex flex-row items-center flex-1 ">
                  <FormLabel></FormLabel>

                  <Select
                    onValueChange={field.onChange}
                    defaultValue="Minute(s)"
                  >
                    <FormControl>
                      <SelectTrigger className="flex-1 items-center">
                        <SelectValue placeholder="Minute(s)" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent className="bg-lightbackground flex-1">
                      {["Day(s)", "Hour(s)", "Minute(s)"].map((value) => (
                        <SelectItem
                          key={value}
                          value={value}
                          className="cursor-pointer transition hover:bg-white hover:text-black"
                        >
                          {value}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </FormItem>
              )}
            />
          </div>
        </div>
        <div>
          <FormField
            control={form.control}
            name="priority"
            render={({ field }) => (
              <FormItem className="flex flex-row items-center gap-x-3">
                <FormLabel>Priority: </FormLabel>

                <Select onValueChange={field.onChange} defaultValue="High">
                  <FormControl>
                    <SelectTrigger className="flex-1">
                      <SelectValue placeholder="High" />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent className="bg-lightbackground flex-1">
                    {["Low", "Medium", "High"].map((value) => (
                      <SelectItem
                        key={value}
                        value={value}
                        className="cursor-pointer transition hover:bg-white hover:text-black"
                      >
                        {value}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>

                <FormMessage />
              </FormItem>
            )}
          />
        </div>
        <Button type="submit" className="bg-lightbackground my-3">
          Submit
        </Button>
      </form>
    </Form>
  );
};

export default CreateReminder;

我收到了一个错误,我不明白这是否有用:

app-index.js:32 Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
    at input
    at _c (webpack-internal:///(app-client)/./components/ui/input.tsx:13:11)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:46:23)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:20:23)
    at eval (webpack-internal:///(app-client)/./components/ui/Form.tsx:124:14)
    at div
    at eval (webpack-internal:///(app-client)/./components/ui/Form.tsx:74:11)
    at Controller (webpack-internal:///(app-client)/./node_modules/react-hook-form/dist/index.esm.mjs:544:37)
    at FormField (webpack-internal:///(app-client)/./components/ui/Form.tsx:29:14)
    at form
    at FormProvider (webpack-internal:///(app-client)/./node_modules/react-hook-form/dist/index.esm.mjs:180:13)
    at CreateReminder (webpack-internal:///(app-client)/./components/CreateReminder.tsx:53:75)
    at div
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dismissable-layer/dist/index.mjs:44:42)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:46:23)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:20:23)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-focus-scope/dist/index.mjs:32:19)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dialog/dist/index.mjs:274:28)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dialog/dist/index.mjs:206:102)
    at $921a889cee6df7e8$export$99c2b779aa4e8b8b (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-presence/dist/index.mjs:28:22)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dialog/dist/index.mjs:191:108)
    at div
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:46:23)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:20:23)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
    at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-portal/dist/index.mjs:24:24)
    at $921a889cee6df7e8$export$99c2b779aa4e8b8b (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-presence/dist/index.mjs:28:22)
    at Provider (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-context/dist/index.mjs:47:28)
    at $5d3850c4d0b4e6c7$export$dad7c95542bacce0 (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dialog/dist/index.mjs:133:28)
    at DialogPortal (webpack-internal:///(app-client)/./components/ui/dialog.tsx:25:11)
    at _c2 (webpack-internal:///(app-client)/./components/ui/dialog.tsx:60:11)
    at Provider (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-context/dist/index.mjs:47:28)
    at $5d3850c4d0b4e6c7$export$3ddf2d174ce01153 (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-dialog/dist/index.mjs:77:28)
    at Modal (webpack-internal:///(app-client)/./components/Modal.tsx:15:11)
    at div
    at div
    at div
    at div
    at Sidebar (webpack-internal:///(app-client)/./components/Sidebar.tsx:15:11)
    at f (webpack-internal:///(app-client)/./node_modules/next-themes/dist/index.module.js:8:597)
    at $ (webpack-internal:///(app-client)/./node_modules/next-themes/dist/index.module.js:8:348)
    at Providers (webpack-internal:///(app-client)/./app/providers/Providers.tsx:7:11)
    at body
    at html
    at RedirectErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9)
    at RedirectBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11)
    at NotFoundErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/not-found-boundary.js:51:9)
    at NotFoundBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/not-found-boundary.js:59:11)
    at ReactDevOverlay (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:66:9)
    at HotReload (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:276:11)
    at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:90:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:80:9)
    at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:106:11)
    at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:387:13)
    at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:154:11)
    at RSCComponent
    at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:171:11)

我在Dialog组件中使用了这个表单,它被有条件地呈现为:

"use client";

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "../components/ui/dialog";
import CreateReminder from "./CreateReminder";

import LoginForm from "./LoginForm";
import RegisterForm from "./RegisterForm";
import Subcategory from "./Subcategory";
import { Button } from "./ui/button";

import { IconType } from "react-icons";

const Modal: React.FC<{ label: string; icon: IconType }> = ({
  label,
  icon,
}) => {
  return (
    <Dialog>
      <DialogTrigger className="w-full">
        <Subcategory label={label} icon={icon} />
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle className="text-center py-2">{label}</DialogTitle>
          <DialogDescription></DialogDescription>
        </DialogHeader>
        {label === "Login" ? (
          <LoginForm />
        ) : label === "Register" ? (
          <RegisterForm />
        ) : (
          <CreateReminder />
        )}
      </DialogContent>
    </Dialog>
  );
};

export default Modal;
5hcedyr0

5hcedyr01#

看起来你需要在定义表单时传递初始值,因为它们一开始是未定义的,然后当你在输入中输入时,它就不再是未定义的了。
当它从undefined变为'some value'时,类型将从不受控变为受控

const form = useForm<ReminderFormSchemaType>({
  resolver: zodResolver(reminderFormSchema),
  initialValues: {
   title: '',
   description: '',
   ...
  }
});

相关问题