Creating reusable text field component using Material UI and react-hook-form
Opened this issue · 0 comments
ranjanmaria commented
I was trying to develop reusable text field component using Material UI and reach-hook-form. I was referring following examples (first one is from react-hook-form docs, second one is this repo):
Can we use this example from react-hook-form
docs to introduce generic type in your FormInputProps
type FormProps<TFormValues> = {
onSubmit: SubmitHandler<TFormValues>;
children: (methods: UseFormReturn<TFormValues>) => React.ReactNode;
};
const Form = <TFormValues extends Record<string, any> = Record<string, any>>({
onSubmit,
children
}: FormProps<TFormValues>) => {
const methods = useForm<TFormValues>();
return (
<form onSubmit={methods.handleSubmit(onSubmit)}>{children(methods)}</form>
);
};
Related code in this repo:
//https://github.com/Mohammad-Faisal/react-hook-form-material-ui/blob/master/src/form-components/FormInputProps.ts
export interface FormInputProps {
name: string;
control: any;
label: string;
setValue?: any;
}
//https://github.com/Mohammad-Faisal/react-hook-form-material-ui/blob/master/src/form-components/FormInputText.tsx
import React from "react";
import { Controller, useFormContext } from "react-hook-form";
import TextField from "@material-ui/core/TextField";
import { FormInputProps } from "./FormInputProps";
export const FormInputText = ({ name, control, label }: FormInputProps) => {
return (
<Controller
name={name}
control={control}
render={({
field: { onChange, value },
fieldState: { error },
formState,
}) => (
<TextField
helperText={error ? error.message : null}
size="small"
error={!!error}
onChange={onChange}
value={value}
fullWidth
label={label}
variant="outlined"
/>
)}
/>
);
};
After analyzing both, I came up with following:
import { TextField } from "@mui/material";
import { Controller, UseFormReturn } from "react-hook-form";
interface IRhfTextBoxProps<TFormValues> {
name: string;
methods: UseFormReturn<TFormValues>;
}
// export const RhfTextBox = <TFormValues extends unknown>(props : IRhfTextBoxProps<TFormValues>) => { //##1
export const RhfTextBox = <TFormValues extends Record<string, any> = Record<string, any>>( // ##2 similar to example 1
props: IRhfTextBoxProps<TFormValues>
) => {
return (
<Controller
control={props.methods.control}
name={props.name} // ##3
render={({ field, fieldState, formState }) => (
<TextField
error={!!fieldState.error}
helperText={fieldState.error?.message ?? ""}
key={props.name}
/>
)}
/>
);
};
But, both lines ##1
and ##2
in above code gives following error at line ##3
:
Type 'string' is not assignable to type 'Path<TFormValues>'.
The detailed error message is as follows:
The expected type comes from property 'name' which is declared here on type 'IntrinsicAttributes & { render: ({ field, fieldState, formState, }: { field: ControllerRenderProps<TFormValues, Path<TFormValues>>; fieldState: ControllerFieldState; formState: UseFormStateReturn<...>; }) => ReactElement<...>; } & UseControllerProps<...>'
Why am I getting this error?