Lys*_* Ng 4 reactjs typescript-generics react-hook-form
上下文:我正在使用react-hook-forms 创建文本字段列表(由控制器控制)。我发现我正在编写相当多的类似代码,并考虑创建一个通用文本字段。
我的问题有两个:
name文本字段的界面属性?我的代码如下:
interface GenericTextfieldProps<T extends FieldValues> {
formLabel: string;
name: keyof T;
control: Control<T>;
};
function GenericTextfield<T extends FieldValues>({
formLabel,
name,
control,
}: GenericTextfieldProps<T>) {
return (
<Stack direction="column" spacing={0.5}>
<Controller
render={({ field }) => (
<TextField
{...field}
id="textfield"
label=""
size="small"
fullWidth
sx={{ ml: 3 }}
disabled
variant="outlined"
/>
)}
name={name}
control={control}
/>
</Stack>
);
}
Run Code Online (Sandbox Code Playgroud)
但是,当我翻译代码以使其更加通用(即通过通用类型进行解析)时, name={name}开始抛出以下字符串错误:
Type 'keyof T' is not assignable to type 'Path<T>'.
对于第一季度:
首先我尝试了 props 中的 name: string 。这不起作用,因为react-hook-forms需要实际的密钥来允许控制器发挥其魔力。
我从9 个月前的这篇文章中确定我可以keyof {my typescript object}在道具中使用。这是非常成功的。
但是,当我翻译代码以使其更加通用(即通过通用类型进行解析)时, name={name}开始抛出以下字符串错误:
Type 'keyof T' is not assignable to type 'Path<T>'.
进一步研究react-hook-forms,似乎有某种相对字段路径需要来自实际打字稿对象的键和值。我也认为这个 stackoverflow 帖子是相关的,但不幸的是那里没有我可以参考的答案。
我认为这与表单如何找到键和值的路径有关(从这里的controller.d.ts文件中收集到:
export declare type UseControllerProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {
name: TName;
rules?: Omit<RegisterOptions<TFieldValues, TName>, 'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'disabled'>;
shouldUnregister?: boolean;
defaultValue?: FieldPathValue<TFieldValues, TName>;
control?: Control<TFieldValues>;
};
Run Code Online (Sandbox Code Playgroud)
理想情况下,如果有人之前这样做过,我会寻找一种以更通用的方式使用react-hook-forms的优雅解决方案。注意:我不打算使用keyOf任何其他解决方案/想法,也欢迎。
小智 7
你走在正确的轨道上UseControllerProps。
UseControllerProps<T>通过使用whereT扩展了props 接口FieldValues,您现在可以设置您想要使用的 Controller props。
import Stack from '@mui/material/Stack';
import TextField from '@mui/material/TextField';
import { Controller, FieldValues, UseControllerProps } from 'react-hook-form';
interface GenericTextfieldProps<T extends FieldValues>
extends UseControllerProps<T> {
formLabel: string;
disabled?: boolean;
}
function GenericTextfield<T extends FieldValues>({
name,
control,
formLabel,
disabled = false,
}: GenericTextfieldProps<T>) {
return (
<Stack direction="column" spacing={0.5}>
<Controller
render={({ field }) => (
<TextField
{...field}
id="textfield"
label={formLabel}
size="small"
fullWidth
sx={{ ml: 3 }}
disabled={disabled}
variant="outlined"
/>
)}
name={name}
control={control}
/>
</Stack>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2317 次 |
| 最近记录: |