网站搜索

reactjs - 使用 shadcn FormField 组件时的类型问题


类型 'foo' 不能赋值给类型 'InputProps'

所以,我正在尝试创建一个可重用的组件,称为 TextInput,它封装了 Shadcn 的 FormField 组件,因为文档显示需要将来自 FormField 渲染方法的 "field" 属性传递给 Input 组件。下面是 TextInput 组件:

import React from "react";
import {
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "./ui/form";
import { Input } from "./ui/input";
import { Control } from "react-hook-form";

type formSchema = {
  title: string;
  description: string;
  image: string;
  location: {
    number: number;
    country: string;
    state: string;
    district: string;
    street: string;
    complement: string;
  };
};

type control = Control<formSchema, any>;

type name = keyof formSchema;

type Props = {
  name: name;
  label: string;
  placeholder: string;
  description?: string;
  control: control;
};

const TextInput = ({
  name,
  label,
  placeholder,
  description,
  control,
}: Props) => {
  return (
    <FormField
      control={control}
      name={name}
      render={({ field }) => (
        <FormItem>
          <FormLabel>{label}</FormLabel>
          <FormControl>
            {/* Here's the problem */}
            <Input {...field} placeholder={placeholder} />
          </FormControl>
          <FormDescription>{description}</FormDescription>
          <FormMessage />
        </FormItem>
      )}
    />
  );
};

export default TextInput;

但是当我传递 'field' 属性时,我从 TypeScript 收到了这个错误消息:

类型 ‘{ placeholder: string; onChange: (...event: any[]) => void; onBlur: Noop; disabled?: boolean | undefined; value: string | { number: number; country: string; state: string; district: string; street: string; complement: string; }; name: keyof formSchema; ref: RefCallBack; }’ 不能分配给类型 ‘InputProps’。属性 ‘value’ 的类型不兼容。类型 ‘string | { number: number; country: string; state: string; district: string; street: string; complement: string; }’ 不能分配给类型 ‘string | number | readonly string[] | undefined’。类型 ‘{ number: number; country: string; state: string; district: string; street: string; complement: string; }’ 不能分配给类型 ‘string | number | readonly string[] | undefined’。

我尝试在 shadcn 和 react-hook-form 的文档中以及互联网上搜索,但我找不到任何关于如何处理它的线索。我最近才开始使用 TypeScript,所以以前从未遇到过这样的情况。我也尝试使用 react-hook-form 的 Controller 输入,但仍然出现这个错误。这里是父组件以提供更多上下文:

"use client";

import { Form, FormField } from "./ui/form";
import { SubmitHandler, useForm } from "react-hook-form";
import TextInput from "./TextInput";
import { Button } from "./ui/button";
import formSchema from "@/utils/meetSchema";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

const MeetUpForm = () => {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
  });

  type Inputs = {};

  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);

  return (
    <Form {...form}>
      <TextInput
        control={form.control}
        label="Title"
        placeholder="Type the meet up title"
        name="title"
      />
      <TextInput
        control={form.control}
        label="Description"
        placeholder="Type the meet up description"
        name="description"
      />
      <TextInput
        control={form.control}
        label="Image"
        placeholder="Type the meet up image URL"
        name="image"
      />
      <h1 className="text-xl font-bold my-4">Location</h1>
      <TextInput
        control={form.control}
        label="Country"
        placeholder="Type the meet up country"
        name="location"
      />
      <TextInput
        control={form.control}
        label="State"
        placeholder="Type the meet up state"
        name="location"
      />
      <TextInput
        control={form.control}
        label="District"
        placeholder="Type the meet up district"
        name="location"
      />
      <TextInput
        control={form.control}
        label="Street"
        placeholder="Type the meet up street"
        name="location"
      />
      <TextInput
        control={form.control}
        label="Number"
        placeholder="Type the meet up number"
        name="location"
      />
      <TextInput
        control={form.control}
        label="Complement"
        placeholder="Type the meet up location complement"
        name="location"
      />
      <Button type="submit">Submit</Button>
    </Form>
  );
};

export default MeetUpForm;

这是一个个人和公共项目,所以你可以在这里查看完整代码:https://github.com/Tonny221/meet-up/tree/dev
欢迎随时给我任何反馈

答案#1

是的,我在我的项目中也遇到了同样的问题,并使用来自“react-hook-form”的 UseFormReturn 类型解决了它。下面我创建了 FormFieldComponent 组件。

有关视频讲解,您可以观看此视频 https://www.youtube.com/watch?v=E3YIY4Xxw88&ab_channel=shirshakKandel

{/* Country and phone */}
        <div className="grid lg:grid-cols-2 lg:gap-4">
          {/* Country */}
          <FormFieldComponent
            form={form}
            isPending={isPending}
            label="Country"
            name="country"
          />

          {/* Phone Number */}
          <FormFieldComponent
            form={form}
            isPending={isPending}
            label="Phone Number(Optional)"
            name="phone"
          />
        </div>

FormFieldComponent 的定义如下。这里 RegisterSchema 是我使用 zod 创建的 schema。

const FormFieldComponent = ({
  form,
  isPending,
  label,  
  name,
  placeholder = "Type here",
}: {  
  form: UseFormReturn<z.infer<typeof RegisterSchema>>;
  isPending: boolean; 
  label: string;
  name: keyof z.infer<typeof RegisterSchema>;
  placeholder?: string;
}) => {
  return (
    <FormField
      control={form.control}
      name={name}
      render={({ field }) => (
        <FormItem>
          <FormLabel>{label}</FormLabel>
          <FormControl>
            <Input {...field} disabled={isPending} placeholder={placeholder} />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />
  );
};