typescript 在“react-hook-form”中使用对象作为值

flseospp  于 2023-01-31  发布在  TypeScript
关注(0)|答案(2)|浏览(203)

描述

我有一个使用对象作为值的组件。
我希望将此组件与react-hook-form一起使用
问题是**react-hook-form认为我的对象是嵌套的窗体控件**

设置

这只是一个例子。
范围日期选择器是此类行为的常见用例
Example codepen
组件接受的值:

type ComponentValue = {
  a: string;
  b: string;
}

该组件:

const Component = ({ value, onChange }: { value: ComponentValue, onChange: (value: ComponentValue) => void }) => {
  return (
    <input value={value.a} onChange={e => onChange({ a: e.target.value, b: (Math.random() * 100 | 0).toString() }) } />
  )
}

形式价值

type FormValues = {
  someField: ComponentValue;
  // other fields
};

默认值:

const defaultValues = {
  someField: {
    a: 'Default a',
    b: 'Default b'
  },
  // other fields
};

useForm用法:

const {
  register,
  handleSubmit,
  formState: { errors },
  control,
} = useForm<FormValues>({
  defaultValues,
});

问题是

将鼠标悬停在(或尝试使用)errors上会显示类型:

const errors: {
  someField?: {
    a?: FieldError | undefined;
    b?: FieldError | undefined;
  } | undefined;
  // other fields
}

但我希望是:

const errors: {
  someField?: FieldError | undefined;
  // other fields
}

总结

我可以强制react-hook-form将我的对象视为一个值而不是嵌套的表单字段吗?

huus2vyu

huus2vyu1#

如果您想在同一个元件中合并2个输入,您可以尝试使用控制器的方法。

export default function App() {
  const { control, handleSubmit, watch } = useForm({
    defaultValues: {
      travel: {
        from: "paris",
        to: "london"
      }
    }
  });

  const onSubmit = (data) => {
    console.log("dans onSubmit", JSON.stringify(data, null, 2));
  };

  return (
    <>
      <h1>Travel</h1>

      <form
        onSubmit={handleSubmit(onSubmit)}
        style={{ display: "flex", flexDirection: "column", maxWidth: 600 }}
        noValidate
      >
        <TravelPicker control={control} />

        <input type="submit" />
        <pre>{JSON.stringify(watch(), null, 2)}</pre>
      </form>
    </>
  );

该组件有一个控制 prop ,能够登记2个输入:

const TravelPicker = ({ control }) => {
  return (
    <>
      <label>
        From
        <Controller
          name="travel.from"
          control={control}
          render={({ field: { onChange, value, name } }) => (
            <input name={name} value={value} onChange={(e) => onChange(e)} />
          )}
        />
      </label>
      <label>
        To
        <Controller
          name="travel.to"
          control={control}
          render={({ field: { onChange, value, name } }) => (
            <input name={name} value={value} onChange={(e) => onChange(e)} />
          )}
        />
      </label>
    </>
  );
};

然后,errors对象具有与表单输入相同的结构。
有关功能示例,请参见sandbox
RHF的创建者似乎在这里表明,您也可以只有一个组件用于2个输入。

ukxgm1gy

ukxgm1gy2#

您可以使用setValuesetError,如下所示:

const {setValue, setError} = useForm();

// ... some where in your form
<input 
  type = "text"
  name = "from"
  onChange = {
    (event) => {
      const value = event.target.value;
      if(value === ""){
        setError("from", "This field is required");
      }else{
        setValue(`from[0]`, {
          "otherProperty" : "otherValue",
          "from_value": value, // this is your input value
        });
      }
    }
  }
/>

您可能会迭代数组。用setValue中的索引更改static 0如果不是,您可以使用如下对象语法:

//....
setValue(`from.your_property_name`, {
    "otherProperty" : "otherValue",
    "from_value": value, // this is your input value
});

// ....

这不会导致组件重新呈现。
doc中的更多信息
注意:请在评论时保持尊重。

相关问题