reactjs React Hook Forms如何使用Typescript将错误作为 prop 传递

9rnv2umw  于 2023-04-05  发布在  React
关注(0)|答案(3)|浏览(156)

我正在定义一个useForm。
const { handleSubmit, control, errors } = useForm<{email: string}>();
现在我正在创建一个单独的组件,它将作为输入,我将传递我在上面创建的useForm prop 。
这就是组件的样子。

type Props<T> = {
  name: FieldName<T>;
  control: Control<T>;
  errors: FieldErrors<T>;
};

const ControlTextInput = <T extends {}>({
  name,
  control,
  errors,
}: Props<T>) => {
  return (
   
    <Controller
    name={name}
    control={control}
    rules={{
      required:'this is required',
    }}
    render={({ onChange }) => (
        <>
            <TextInput
                onChangeText={(text) => {
                onChange(text);
                }}
            />
            {/* Show my error here */}
            {errors.email && (
                <Text style={{ color: "red" }}>
                    {errors.email?.message}
                </Text>
            )}
      </>
    )}
  />
  );
};

我想这样使用组件。

<ControlTextInput<AnyObject>
                    name="email"
                    errors={errors}
                    control={control}
                  />

当鼠标悬停在errors.email

上时,出现此错误

jecbmhm3

jecbmhm31#

React Hook Form公开了UseControllerProps类型,它接受泛型类型T,T可以推断出你的输入值类型,换句话说就是FieldValues类型。最初,你通过将字段的类型传递给useForm钩子来定义FieldValues类型(参见下面的MyInputTypes)。

interface MyInputTypes {
  email: string;
  password: string;
}

const { register, handleSubmit, watch, formState: { errors } } = useForm<MyInputTypes>();

这意味着您可以创建扩展UseControllerProps并具有泛型T interface Props<T> extends UseControllerProps<T> {}的接口。类型UseControllerProps已经包含namecontrol的类型定义,因此您不需要在接口中单独定义它们(除非您想这样做或有特殊要求/原因这样做)。关于errors适当的解决方案Imo(因为你只需要关于单个字段的错误)将直接传递类型为FieldError | undefined的特定错误。结果看起来像下面的代码。

interface Props<T> extends UseControllerProps<T> {
  error: FieldError | undefined
}

然后,您可以简单地使用ControlTextInput,如下所示。

<ControlTextInput name="email" error={errors.email} />

在Component(使用ControlTextInput)中,泛型T必须扩展FieldValues,因为最终,正是这个类型推断了字段的类型。
例如ControlTextInput

import React from 'react';
import { Controller, FieldError, FieldValues, UseControllerProps } from 'react-hook-form';

interface Props<T> extends UseControllerProps<T> {
  error: FieldError | undefined;
}

const ControlTextInput = <T extends FieldValues>({ name, control, error }: Props<T>) => {
  return (
    <Controller
      name={name}
      control={control}
      rules={{
        required: 'This is required',
      }}
      render={({ field: { onChange } }) => (
        <>
          <input
            onChange={(text) => {
              onChange(text);
            }}
          />
          {error && <span style={{ color: 'red' }}>{error?.message}</span>}
        </>
      )}
    />
  );
};

export default ControlTextInput;

作为使用ControlTextInput的示例组件

import React, { FunctionComponent } from 'react';
import { useForm } from 'react-hook-form';
import ControlTextInput from './ControlTextInput';

interface InputTypes {
  email: string;
  password: string;
}

const Foo: FunctionComponent = () => {
  const {
    formState: { errors },
  } = useForm<InputTypes>();
  return <ControlTextInput name='email' error={errors.email} />;
};

export default Foo;

以下是一些截图,其中包含或多或少模仿您的方法和解决方案的现成代码(与上述StackOverflow的新代码相同)。
ControlTextInput
Component which uses ControlTextInput

vyswwuz2

vyswwuz22#

让我向你展示如何输入props来将errorsregister方法传递给子组件(基于ChakraUI):

interface Props<T extends FieldValues> extends UseControllerProps<T> {
    errors: FieldErrors<IFormData>;
    register: UseFormRegister<IFormData>;
}

export const Form = <T extends FieldValues>({
    register,
    errors,
}: Props<T>) => {

表格内容:

<FormControl isInvalid={errors?.name? true : false}>
    <Input
        type="text"
        placeholder="Name"
        {...register('name', {
            required: 'This field is required',
        })}
    />
    {errors?.modelName && (
        <FormErrorMessage>
            {errors?.name?.message}
        </FormErrorMessage>
    )}
</FormControl>

父组件:

export interface IFormData {
    name: string;
}
const {
    register,
    handleSubmit,
    control,
    formState: { errors, isSubmitting },
} = useForm<IFormData>({
    mode: 'onChange',
});

<form onSubmit={handleUpload}>
            <Form
                register={register}
                errors={errors}
                name={''}
            />
</form>
pdsfdshx

pdsfdshx3#

我找到解决方案的方法是使用错误类型any errors?: any;
使用lodash get函数const errName = get(errors, name);
然后我可以得到错误已经跟随。
{errName && <Text style={{ color: "red" }}>{errName.message}</Text>}

相关问题