React Hook Form受控输入的输入问题

huangapple go评论73阅读模式
英文:

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 &lt;Controller&gt; component to wrap the 3rd party component.

This is working well like this:

&lt;Controller
    control={control}
    name={&quot;Value&quot;}
    rules={{ required: true }}
    render={({ field, fieldState, formState }) =&gt; (
      &lt;TextField
        value={field.value}
        errorMessage={fieldState.error?.message}
        label={field.name}
        description={&quot;Value of the property&quot;}
        onChange={(_, value) =&gt; field.onChange(value)}
        onBlur={field.onBlur}
        required
      /&gt;
    )}
  /&gt;

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:


&lt;ControlledTextField
    control={control}
    name={&#39;Value&#39;}
    rules={{ required: true }}
    label={&#39;Value&#39;}
    description={&quot;Value of the property&quot;}
    required
/&gt;

In order to achieve that, I tried this:

type ControllerPropsEx = Omit&lt;ControllerProps, &quot;render&quot; | &quot;control&quot; | &quot;name&quot;&gt;;

// Base type for controlled inputs
type ControlledType&lt;F extends FieldValues, T&gt; = {
  name: Path&lt;F&gt;;
  control: Control&lt;F&gt;;
  controllerProps?: ControllerPropsEx;
} &amp; T;

// props specific to TextField component, combined with controller props 
// and where I remove props actually managed by react hook form
type ControlledTextFieldProps&lt;F extends FieldValues&gt; = ControlledType&lt;
  F,
  Omit&lt;ITextFieldProps, &quot;onChange&quot; | &quot;onBlur&quot; | &quot;value&quot; | &quot;errorMessage&quot;&gt; // Remove all properties that is already handled by the controller
&gt;;

const ControlledTextField = &lt;F extends FieldValues&gt;({
  name,
  control,
  controllerProps,
  ...props
}: ControlledTextFieldProps&lt;F&gt;): JSX.Element =&gt; {
  return (
    &lt;Controller
      name={name}
      control={control}
      {...controllerProps}
      render={({
        field: { onBlur, onChange, value, name },
        fieldState: { error }
      }) =&gt; (
        &lt;TextField
          {...props}
          name={name}
          value={value || &quot;&quot;}
          onChange={onChange}
          onBlur={onBlur}
          errorMessage={error?.message}
        /&gt;
      )}
    /&gt;
  );
};

However, this yield compilation errors. I get Type &#39;Control&lt;F, any&gt;&#39; is not assignable to type &#39;Control&lt;FieldValues, any&gt;&#39; 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&lt;F extends FieldValues&gt; = Omit&lt;
  ControllerProps&lt;F&gt;, // Here, I added &lt;F&gt; parameter
  &quot;render&quot; | &quot;control&quot; | &quot;name&quot;
&gt;;

// Base type for controlled inputs
type ControlledType&lt;F extends FieldValues, T&gt; = {
  name: Path&lt;F&gt;;
  control: Control&lt;F&gt;;
  controllerProps?: ControllerPropsEx&lt;F&gt;;
} &amp; T;

huangapple
  • 本文由 发表于 2023年2月24日 04:57:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550247.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定