React Hook Forms 如何使用 Typescript 将错误作为道具传递
React Hook Forms How to pass the errors as a props using Typescript
我正在定义一个 useForm。
const { handleSubmit, control, errors } = useForm<{email: string}>();
现在我正在创建一个单独的组件来输入,我将传递我在上面创建的 useForm
道具。
这就是组件的样子。
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
上时出现此错误
我找到解决方案的方法是使用错误类型 any
errors?: any;
使用lodash get函数
const errName = get(errors, name);
然后我可以得到错误如下。
{errName && <Text style={{ color: "red" }}>{errName.message}</Text>}
React Hook Form 公开类型 UseControllerProps
,它接受通用类型 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
已经包含 name
和 control
的类型定义,因此您不需要在界面中单独定义它们(除非您想要或有特殊要求/原因)所以)。关于 errors
适当的解决方案 Imo(因为您只需要有关单个字段的错误)将直接传递类型为 FieldError | undefined
的特定错误。结果如下代码所示。
interface Props<T> extends UseControllerProps<T> {
error: FieldError | undefined
}
然后您可以简单地使用您的 ControlTextInput,如下所示。
<ControlTextInput name="email" error={errors.email} />
在组件(使用 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;
这里有现成代码的屏幕截图,它们或多或少地模仿了您的方法和解决方案(与上面的 Whosebug 新代码相同)。
ControlTextInput
Component which uses ControlTextInput
我正在定义一个 useForm。
const { handleSubmit, control, errors } = useForm<{email: string}>();
现在我正在创建一个单独的组件来输入,我将传递我在上面创建的 useForm
道具。
这就是组件的样子。
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
上时出现此错误
我找到解决方案的方法是使用错误类型 any
errors?: any;
使用lodash get函数
const errName = get(errors, name);
然后我可以得到错误如下。
{errName && <Text style={{ color: "red" }}>{errName.message}</Text>}
React Hook Form 公开类型 UseControllerProps
,它接受通用类型 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
已经包含 name
和 control
的类型定义,因此您不需要在界面中单独定义它们(除非您想要或有特殊要求/原因)所以)。关于 errors
适当的解决方案 Imo(因为您只需要有关单个字段的错误)将直接传递类型为 FieldError | undefined
的特定错误。结果如下代码所示。
interface Props<T> extends UseControllerProps<T> {
error: FieldError | undefined
}
然后您可以简单地使用您的 ControlTextInput,如下所示。
<ControlTextInput name="email" error={errors.email} />
在组件(使用 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;
这里有现成代码的屏幕截图,它们或多或少地模仿了您的方法和解决方案(与上面的 Whosebug 新代码相同)。
ControlTextInput
Component which uses ControlTextInput