TypeScript 中 FieldArray 的 Redux 表单验证
Redux Form Validation for FieldArray in TypeScript
我第一次从 redux-form 实现 FieldArray 并且 UI 工作正常(尽管似乎有一些我还没有诊断出的一般性能暗示)。这个想法是你点击一个添加按钮来添加另一个“房间”到表单,它只是一个文本字段(忽略按钮组件,它是一个自定义组件)
但是验证代码无法编译。看来我在类型上发生冲突,并且不确定在打字稿中做这件事的正确方法。我正在使用 this example 中关于如何进行验证的指南,但该示例纯粹是 javascript.
错误是:
Type '{ _error: string; }' is not assignable to type 'string | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | undefined'.
这是呈现字段数组的方法:
const renderRoomNames = (fieldProps: WrappedFieldArrayProps<string>) => (
<Grid container spacing={4}>
{fieldProps.fields.map((name: string, index: number) => {
console.log('room - name', name);
return (
<Grid item xs={12} key={`gridroom${index + 1}`}>
<Field
name={`${name}`}
type="text"
label={"Room " + (index + 1)}
placeholder={`Enter a name for this room`}
component={ReduxFormTextField}
required={true}
disabled={isSuccessful}
fullWidth
/>
</Grid>
)})}
<Grid item xs={12}>
<StandardButtonBase
variant="contained"
color="primary"
startIcon={<AddIcon />}
align="right"
disableTooltip={true}
round={true}
onClick={() => fieldProps.fields.push('')}
buttonText="Add Room"
/>
{fieldProps.meta.submitFailed && fieldProps.meta.error && <span>{fieldProps.meta.error}</span>}
</Grid>
</Grid>
)
return (
<FieldArray name="roomNames" component={renderRoomNames} />
)
验证码:
export const requestVirtualClinicFormDataValidator = (
model?: IModel
): FormErrors<IModel> => {
const errors: FormErrors<IModel> = {};
if (!model) {
errors._error = 'SNIP';
return errors;
}
// General room name errors checked first
if (isEmpty(model.roomNames) || model.roomNames.length === 0) {
errors.roomNames = 'You require at least one room '
} else if (model.roomNames.some((x) => isEmpty(x))) {
errors.roomNames = { _error: 'All room names must have a value' };
} else {
// Specific individual room name checks second
const roomNameErrors:any[] = [];
if (model.roomNames.length === 1 && isEmpty(model.roomNames[0])) {
roomNameErrors[0] = { _error: 'You must provide a name for your room' };
} else {
for (let i=0; i < model.roomNames.length; i++) {
const roomName = model.roomNames[i];
const count = model.roomNames.filter(x => x.toLowerCase() === roomName.toLowerCase()).length;
if (count > 1) {
roomNameErrors[i] = { _error: 'All rooms must have a unique name' }
}
}
if (roomNameErrors && roomNameErrors.length > 0) {
errors.roomNames = roomNameErrors;
}
}
}
return errors;
};
问题出在编译上。它不喜欢 _error:
部分,它想要一个直的字符串。
但是,如果将 roomNameErrors 保留为字符串数组,它也不允许行 errors.roomNames = roomNameErrors;
。这反而会导致此错误:
Type 'string[]' is not assignable to type 'string | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | undefined'.
似乎即使我的模型上的 'roomNames' 属性 是一个字符串数组,它的类型定义只需要反应组件或字符串。如何使用打字稿传回字段数组中给定字段的验证失败?前面链接的示例根本不传递当前设置的打字稿类型。
使用 redux-form 8.2.
我发现类型定义确实是错误的。
通过将错误从 FormErrors 切换为 Any 类型,它全部编译并实际工作。我将记录一个明确类型的回购问题来解决这个问题。
我第一次从 redux-form 实现 FieldArray 并且 UI 工作正常(尽管似乎有一些我还没有诊断出的一般性能暗示)。这个想法是你点击一个添加按钮来添加另一个“房间”到表单,它只是一个文本字段(忽略按钮组件,它是一个自定义组件)
但是验证代码无法编译。看来我在类型上发生冲突,并且不确定在打字稿中做这件事的正确方法。我正在使用 this example 中关于如何进行验证的指南,但该示例纯粹是 javascript.
错误是:
Type '{ _error: string; }' is not assignable to type 'string | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | undefined'.
这是呈现字段数组的方法:
const renderRoomNames = (fieldProps: WrappedFieldArrayProps<string>) => (
<Grid container spacing={4}>
{fieldProps.fields.map((name: string, index: number) => {
console.log('room - name', name);
return (
<Grid item xs={12} key={`gridroom${index + 1}`}>
<Field
name={`${name}`}
type="text"
label={"Room " + (index + 1)}
placeholder={`Enter a name for this room`}
component={ReduxFormTextField}
required={true}
disabled={isSuccessful}
fullWidth
/>
</Grid>
)})}
<Grid item xs={12}>
<StandardButtonBase
variant="contained"
color="primary"
startIcon={<AddIcon />}
align="right"
disableTooltip={true}
round={true}
onClick={() => fieldProps.fields.push('')}
buttonText="Add Room"
/>
{fieldProps.meta.submitFailed && fieldProps.meta.error && <span>{fieldProps.meta.error}</span>}
</Grid>
</Grid>
)
return (
<FieldArray name="roomNames" component={renderRoomNames} />
)
验证码:
export const requestVirtualClinicFormDataValidator = (
model?: IModel
): FormErrors<IModel> => {
const errors: FormErrors<IModel> = {};
if (!model) {
errors._error = 'SNIP';
return errors;
}
// General room name errors checked first
if (isEmpty(model.roomNames) || model.roomNames.length === 0) {
errors.roomNames = 'You require at least one room '
} else if (model.roomNames.some((x) => isEmpty(x))) {
errors.roomNames = { _error: 'All room names must have a value' };
} else {
// Specific individual room name checks second
const roomNameErrors:any[] = [];
if (model.roomNames.length === 1 && isEmpty(model.roomNames[0])) {
roomNameErrors[0] = { _error: 'You must provide a name for your room' };
} else {
for (let i=0; i < model.roomNames.length; i++) {
const roomName = model.roomNames[i];
const count = model.roomNames.filter(x => x.toLowerCase() === roomName.toLowerCase()).length;
if (count > 1) {
roomNameErrors[i] = { _error: 'All rooms must have a unique name' }
}
}
if (roomNameErrors && roomNameErrors.length > 0) {
errors.roomNames = roomNameErrors;
}
}
}
return errors;
};
问题出在编译上。它不喜欢 _error:
部分,它想要一个直的字符串。
但是,如果将 roomNameErrors 保留为字符串数组,它也不允许行 errors.roomNames = roomNameErrors;
。这反而会导致此错误:
Type 'string[]' is not assignable to type 'string | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | undefined'.
似乎即使我的模型上的 'roomNames' 属性 是一个字符串数组,它的类型定义只需要反应组件或字符串。如何使用打字稿传回字段数组中给定字段的验证失败?前面链接的示例根本不传递当前设置的打字稿类型。
使用 redux-form 8.2.
我发现类型定义确实是错误的。 通过将错误从 FormErrors 切换为 Any 类型,它全部编译并实际工作。我将记录一个明确类型的回购问题来解决这个问题。