Reputation: 23
So, I'm trying to make a reusable component called TextInput that wraps the Shadcn FormField component, as the documentation shows its need to pass to Input component a "field" props that's come from the render method of the FormField. Here's the TextInput component:
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;
But when I pass the 'field' props I'm getting this error message from typescript:
Type '{ 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; }' is not assignable to type 'InputProps'. Types of property 'value' are incompatible. Type 'string | { number: number; country: string; state: string; district: string; street: string; complement: string; }' is not assignable to type 'string | number | readonly string[] | undefined'. Type '{ number: number; country: string; state: string; district: string; street: string; complement: string; }' is not assignable to type 'string | number | readonly string[] | undefined'.
I tried to search both on shadcn and react-hook-form documentation and even on the Internet but I cannot find no clue on how to deal with it, I starded working recently with typescript so I never had a problem like this before. I also tried using the Controller input from react-hook-form but it's still getting this error. Here's the parent component for more context:
"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;
This is a personal and public project, so you can check the full code here: https://github.com/Tonny221/meet-up/tree/dev
Fell free to give me any feedback
Upvotes: 2
Views: 2396
Reputation: 609
Yes I faced the same problem in my projects and fix it using UseFormReturn type from "react-hook-form". Below I make FormFieldComponent component.
For Video Explanation you can watch this video 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>
Definition of FormFieldComponent is like below. Here RegisterSchema is schema i made using zod.
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>
)}
/>
);
};
Upvotes: 0