Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/examples/validate-perf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import Form, { Field, FormInstance } from 'rc-field-form';
import Input from './components/Input';
import LabelField from './components/LabelField';
import { ValidateMessages } from '@/interface';
import { Message, ValidateMessages } from '@/interface';

const myMessages: ValidateMessages = {
default: '${name} 看起来怪怪的……',
Expand Down Expand Up @@ -34,7 +34,7 @@ export default class Demo extends React.Component {
console.log('Failed:', errorInfo);
};

public onPasswordError = ({ errors }: { errors: string[] }) => {
public onPasswordError = ({ errors }: { errors: Message[] }) => {
console.log('🐞 Password Error:', errors);
};

Expand Down
17 changes: 9 additions & 8 deletions src/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
InternalFormInstance,
InternalNamePath,
InternalValidateOptions,
Message,
Meta,
NamePath,
NotifyInfo,
Expand All @@ -29,8 +30,8 @@ import {
getValue,
} from './utils/valueUtil';

const EMPTY_ERRORS: any[] = [];
const EMPTY_WARNINGS: any[] = [];
const EMPTY_ERRORS: never[] = [];
const EMPTY_WARNINGS: never[] = [];

export type ShouldUpdate<Values = any> =
| boolean
Expand Down Expand Up @@ -137,12 +138,12 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
*/
private dirty: boolean = false;

private validatePromise: Promise<string[]> | null;
private validatePromise: Promise<RuleError[]> | null;

private prevValidating: boolean;

private errors: string[] = EMPTY_ERRORS;
private warnings: string[] = EMPTY_WARNINGS;
private errors: Message[] = EMPTY_ERRORS;
private warnings: Message[] = EMPTY_WARNINGS;

// ============================== Subscriptions ==============================
constructor(props: InternalFieldProps) {
Expand Down Expand Up @@ -392,7 +393,7 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
const { triggerName, validateOnly = false } = options || {};

// Force change to async to avoid rule OOD under renderProps field
const rootPromise = Promise.resolve().then(async (): Promise<any[]> => {
const rootPromise = Promise.resolve().then(async (): Promise<RuleError[]> => {
if (!this.mounted) {
return [];
}
Expand Down Expand Up @@ -442,8 +443,8 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
this.validatePromise = null;

// Get errors & warnings
const nextErrors: string[] = [];
const nextWarnings: string[] = [];
const nextErrors: Message[] = [];
const nextWarnings: Message[] = [];
ruleErrors.forEach?.(({ rule: { warningOnly }, errors = EMPTY_ERRORS }) => {
if (warningOnly) {
nextWarnings.push(...errors);
Expand Down
30 changes: 16 additions & 14 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ export type NamePath<T = any> = DeepNamePath<T>;
export type StoreValue = any;
export type Store = Record<string, StoreValue>;

export type Message = string | ReactElement;

export interface Meta {
touched: boolean;
validating: boolean;
errors: string[];
warnings: string[];
errors: Message[];
warnings: Message[];
name: InternalNamePath;
validated: boolean;
}
Expand Down Expand Up @@ -54,7 +56,7 @@ export type RuleRender = (form: FormInstance) => RuleObject;

export interface ValidatorRule {
warningOnly?: boolean;
message?: string | ReactElement;
message?: Message;
validator: Validator;
}

Expand All @@ -63,7 +65,7 @@ interface BaseRule {
enum?: StoreValue[];
len?: number;
max?: number;
message?: string | ReactElement;
message?: Message;
min?: number;
pattern?: RegExp;
required?: boolean;
Expand All @@ -87,9 +89,9 @@ export type RuleObject = AggregationRule | ArrayRule;
export type Rule = RuleObject | RuleRender;

export interface ValidateErrorEntity<Values = any> {
message: string;
message: Message;
values: Values;
errorFields: { name: InternalNamePath; errors: string[] }[];
errorFields: { name: InternalNamePath; errors: Message[] }[];
outOfDate: boolean;
}

Expand All @@ -108,8 +110,8 @@ export interface FieldEntity {
validateRules: (options?: InternalValidateOptions) => Promise<RuleError[]>;
getMeta: () => Meta;
getNamePath: () => InternalNamePath;
getErrors: () => string[];
getWarnings: () => string[];
getErrors: () => Message[];
getWarnings: () => Message[];
props: {
name?: NamePath;
rules?: Rule[];
Expand All @@ -126,12 +128,12 @@ export interface FieldEntity {

export interface FieldError {
name: InternalNamePath;
errors: string[];
warnings: string[];
errors: Message[];
warnings: Message[];
}

export interface RuleError {
errors: string[];
errors: Message[];
rule: RuleObject;
}

Expand Down Expand Up @@ -271,9 +273,9 @@ export interface FormInstance<Values = any> {
getFieldsValue: (() => Values) &
((nameList: NamePath<Values>[] | true, filterFunc?: FilterFunc) => any) &
((config: GetFieldsValueConfig) => any);
getFieldError: (name: NamePath<Values>) => string[];
getFieldError: (name: NamePath<Values>) => Message[];
getFieldsError: (nameList?: NamePath<Values>[]) => FieldError[];
getFieldWarning: (name: NamePath<Values>) => string[];
getFieldWarning: (name: NamePath<Values>) => Message[];
isFieldsTouched: ((nameList?: NamePath<Values>[], allFieldsTouched?: boolean) => boolean) &
((allFieldsTouched?: boolean) => boolean);
isFieldTouched: (name: NamePath<Values>) => boolean;
Expand Down Expand Up @@ -314,7 +316,7 @@ export type InternalFormInstance = Omit<FormInstance, 'validateFields'> & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type EventArgs = any[];

type ValidateMessage = string | (() => string);
type ValidateMessage = string | (() => string) | ReactElement;
export interface ValidateMessages {
default?: ValidateMessage;
required?: ValidateMessage;
Expand Down
13 changes: 7 additions & 6 deletions src/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
InternalNamePath,
InternalValidateFields,
InternalValidateOptions,
Message,
Meta,
NamePath,
NotifyInfo,
Expand Down Expand Up @@ -382,15 +383,15 @@ export class FormStore {
});
};

private getFieldError = (name: NamePath): string[] => {
private getFieldError = (name: NamePath): Message[] => {
this.warningUnhooked();

const namePath = getNamePath(name);
const fieldError = this.getFieldsError([namePath])[0];
return fieldError.errors;
};

private getFieldWarning = (name: NamePath): string[] => {
private getFieldWarning = (name: NamePath): Message[] => {
this.warningUnhooked();

const namePath = getNamePath(name);
Expand Down Expand Up @@ -877,7 +878,7 @@ export class FormStore {
* Fill errors since `fields` may be replaced by controlled fields
*/
if (filedErrors) {
const cache = new NameMap<string[]>();
const cache = new NameMap<Message[]>();
filedErrors.forEach(({ name, errors }) => {
cache.set(name, errors);
});
Expand Down Expand Up @@ -971,8 +972,8 @@ export class FormStore {
promise
.then<any, RuleError>(() => ({ name: fieldNamePath, errors: [], warnings: [] }))
.catch((ruleErrors: RuleError[]) => {
const mergedErrors: string[] = [];
const mergedWarnings: string[] = [];
const mergedErrors: Message[] = [];
const mergedWarnings: Message[] = [];
Comment on lines +975 to +976

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While updating these types to Message[] is correct, a related type annotation in this file was missed and should also be updated to prevent potential runtime errors and ensure type consistency.

In the catch block for returnPromise within the validateFields method (around line 1025), the errors property in the type for the results parameter is still string[]. It should be Message[].

Suggested Change:

In src/useForm.ts around line 1025, please update the type signature:

// before
.catch((results: { name: InternalNamePath; errors: string[] }[]) => {

// after
.catch((results: { name: InternalNamePath; errors: Message[] }[]) => {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed that by using FieldError


ruleErrors.forEach?.(({ rule: { warningOnly }, errors }) => {
if (warningOnly) {
Expand Down Expand Up @@ -1021,7 +1022,7 @@ export class FormStore {
}
return Promise.reject<string[]>([]);
})
.catch((results: { name: InternalNamePath; errors: string[] }[]) => {
.catch((results: FieldError[]) => {
const errorList = results.filter(result => result && result.errors.length);
const errorMessage = errorList[0]?.errors?.[0];
return Promise.reject({
Expand Down