reactjs - Använd generisk som skickas till useForm i anpassad kontrollkomponent
Genom att använda react-hook-form försöker jag göra en egen ControlledTextField-komponent som fungerar med mitt komponentbibliotek. Följande TypeScript-användning för userForm kan jag skapa mitt formulär på detta sätt
export interface AuthenticationData {
email: string,
password: string
}
const { handleSubmit, control } = useForm<AuthenticationData>({
resolver: yupResolver(LoginSchema),
})
Sedan skapar jag min anpassade ControlledTextField-komponent
import { FormControl, Input } from "native-base"
import { Controller, UseControllerProps } from "react-hook-form"
interface ControlledTextFieldProps extends UseControllerProps {
label: string
}
const ControlledTextField = ({ control, name, label, ...props }: ControlledTextFieldProps) => {
return (
<Controller
control={control}
name={name}
render={({
fieldState: { invalid, error },
field: { onChange, onBlur, value },
}) => (
<FormControl mb="5" isInvalid={invalid}>
<FormControl.Label>{label}</FormControl.Label>
<Input
onBlur={onBlur}
onChange={onChange}
value={value}
/>
<FormControl.ErrorMessage>
{error?.message ?? ""}
</FormControl.ErrorMessage>
</FormControl>
)}
/>
)
}
export default ControlledTextField
När jag försöker implementera får jag detta fel
Type 'Control<AuthenticationData, any>' is not assignable to type 'Control<FieldValues, any>'.
The types of '_options.resolver' are incompatible between these types.
Type 'Resolver<AuthenticationData, any> | undefined' is not assignable to type 'Resolver<FieldValues, any> | undefined'.
Type 'Resolver<AuthenticationData, any>' is not assignable to type 'Resolver<FieldValues, any>
Implementeringen ser ut så här...
<ControlledTextField
name="email"
label="Email"
control={control}
/>
Svar #1
Jag har också stött på det här problemet. Lösningen jag kom fram till var att skicka Control-prop:n med en generisk typ som utökar FieldValues-typen till ControlledTextField-komponenten. Från och med då bör du kunna få olika variabler med de korrekt härledda typerna.
Komponentimplementeringen bör se ut ungefär så här:
import { FormControl, Input } from "native-base"
import { Controller, UseControllerProps, Control, FieldPath, FieldValues } from "react-hook-form"
interface ControlledTextFieldProps<T extends FieldValues> extends UseControllerProps {
label: string;
control: Control<T>;
name: FieldPath<T>;
defaultValue: T[keyof T];
}
const ControlledTextField = ({ control, name, label, defaultValue, ...props }: ControlledTextFieldProps) => {
return (
<Controller
control={control}
name={name}
render={({
fieldState: { invalid, error },
field: { onChange, onBlur, value },
}) => (
<FormControl mb="5" isInvalid={invalid}>
<FormControl.Label>{label}</FormControl.Label>
<Input
onBlur={onBlur}
onChange={onChange}
value={value}
/>
<FormControl.ErrorMessage>
{error?.message ?? ""}
</FormControl.ErrorMessage>
</FormControl>
)}
/>
)
}
export default ControlledTextField
Och sedan, när du implementerar komponenten:
<ControlledTextField
name="email"
label="Email"
control={control}
defaultValue=""
/>
