英文:
Typing issue with react hook form controlled input
问题
I use react-hook-forms
in my application. The application uses the office-ui-fabric-react
library.
In order to incorporate the framework inputs, I use the <Controller>
component to wrap the 3rd party component.
This is working well like this:
<Controller
control={control}
name={"Value"}
rules={{ required: true }}
render={({ field, fieldState, formState }) => (
<TextField
value={field.value}
errorMessage={fieldState.error?.message}
label={field.name}
description={"Value of the property"}
onChange={(_, value) => field.onChange(value)}
onBlur={field.onBlur}
required
/>
)}
/>
But because this pattern is quite verbose, I want to isolate this into a ControlledTextField
component.
I expect to be able to use it like this:
<ControlledTextField
control={control}
name={'Value'}
rules={{ required: true }}
label={'Value'}
description={"Value of the property"}
required
/>
In order to achieve that, I tried this:
type ControllerPropsEx = Omit<ControllerProps, "render" | "control" | "name">;
// Base type for controlled inputs
type ControlledType<F extends FieldValues, T> = {
name: Path<F>;
control: Control<F>;
controllerProps?: ControllerPropsEx;
} & T;
// props specific to TextField component, combined with controller props
// and where I remove props actually managed by react hook form
type ControlledTextFieldProps<F extends FieldValues> = ControlledType<
F,
Omit<ITextFieldProps, "onChange" | "onBlur" | "value" | "errorMessage"> // Remove all properties that are already handled by the controller
>;
const ControlledTextField = <F extends FieldValues>({
name,
control,
controllerProps,
...props
}: ControlledTextFieldProps<F>): JSX.Element => {
return (
<Controller
name={name}
control={control}
{...controllerProps}
render={({ field: { onBlur, onChange, value, name }, fieldState: { error } }) => (
<TextField
{...props}
name={name}
value={value || ""}
onChange={onChange}
onBlur={onBlur}
errorMessage={error?.message}
/>
)}
/>
);
};
However, this yields compilation errors. I get the Type 'Control<F, any>' is not assignable to type 'Control<FieldValues, any>'
error on control={control}
.
How can I properly type my component's props?
Here's a full code sandbox repro (look into NonWorkingForm.tsx file).
英文:
I use react-hook-forms
in my application. The application use office-ui-fabric-react
library.
In order to incorporate the framework inputs, I use the <Controller>
component to wrap the 3rd party component.
This is working well like this:
<Controller
control={control}
name={"Value"}
rules={{ required: true }}
render={({ field, fieldState, formState }) => (
<TextField
value={field.value}
errorMessage={fieldState.error?.message}
label={field.name}
description={"Value of the property"}
onChange={(_, value) => field.onChange(value)}
onBlur={field.onBlur}
required
/>
)}
/>
But because this pattern is quite verbose, I want to isolate this into a ControlledTextField
component.
I expect to be able to use it like this:
<ControlledTextField
control={control}
name={'Value'}
rules={{ required: true }}
label={'Value'}
description={"Value of the property"}
required
/>
In order to achieve that, I tried this:
type ControllerPropsEx = Omit<ControllerProps, "render" | "control" | "name">;
// Base type for controlled inputs
type ControlledType<F extends FieldValues, T> = {
name: Path<F>;
control: Control<F>;
controllerProps?: ControllerPropsEx;
} & T;
// props specific to TextField component, combined with controller props
// and where I remove props actually managed by react hook form
type ControlledTextFieldProps<F extends FieldValues> = ControlledType<
F,
Omit<ITextFieldProps, "onChange" | "onBlur" | "value" | "errorMessage"> // Remove all properties that is already handled by the controller
>;
const ControlledTextField = <F extends FieldValues>({
name,
control,
controllerProps,
...props
}: ControlledTextFieldProps<F>): JSX.Element => {
return (
<Controller
name={name}
control={control}
{...controllerProps}
render={({
field: { onBlur, onChange, value, name },
fieldState: { error }
}) => (
<TextField
{...props}
name={name}
value={value || ""}
onChange={onChange}
onBlur={onBlur}
errorMessage={error?.message}
/>
)}
/>
);
};
However, this yield compilation errors. I get Type 'Control<F, any>' is not assignable to type 'Control<FieldValues, any>'
error on control={control}
How can I properly type my component's prop ?
Here's a full code sandbox repro (look into NonWorkingForm.tsx file)
答案1
得分: 0
我发现了这个问题(问题很微妙)。
我必须像这样传递通用参数给 ControllerProps
:
type ControllerPropsEx<F extends FieldValues> = Omit<
ControllerProps<F>, // 这里,我添加了 <F> 参数
"render" | "control" | "name"
>;
// 受控输入的基本类型
type ControlledType<F extends FieldValues, T> = {
name: Path<F>;
control: Control<F>;
controllerProps?: ControllerPropsEx<F>;
} & T;
英文:
I spotted the issue (which is subtle).
I had to pass generic argument to ControllerProps
like this:
type ControllerPropsEx<F extends FieldValues> = Omit<
ControllerProps<F>, // Here, I added <F> parameter
"render" | "control" | "name"
>;
// Base type for controlled inputs
type ControlledType<F extends FieldValues, T> = {
name: Path<F>;
control: Control<F>;
controllerProps?: ControllerPropsEx<F>;
} & T;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论