Skip to content

Commit ce3fdd2

Browse files
committed
refactor: use onMetaChange instead of onErrors
1 parent 32cd8f6 commit ce3fdd2

File tree

2 files changed

+60
-40
lines changed

2 files changed

+60
-40
lines changed

src/Field.tsx

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
defaultGetValueFromEvent,
2626
getNamePath,
2727
getValue,
28-
isSimilar,
2928
} from './utils/valueUtil';
3029

3130
const EMPTY_ERRORS: any[] = [];
@@ -77,7 +76,7 @@ export interface InternalFieldProps<Values = any> {
7776
messageVariables?: Record<string, string>;
7877
initialValue?: any;
7978
onReset?: () => void;
80-
onError?: (errors: string[], warnings: string[]) => void;
79+
onMetaChange?: (meta: Meta) => void;
8180
preserve?: boolean;
8281

8382
/** @private Passed by Form.List props. Do not use since it will break by path check. */
@@ -216,20 +215,11 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
216215
}));
217216
};
218217

219-
/** Update `this.error`. If `onError` provided, trigger it */
220-
public updateError(
221-
prevErrors: string[],
222-
nextErrors: string[],
223-
prevWarnings: string[],
224-
nextWarnings: string[],
225-
) {
226-
const { onError } = this.props;
227-
if (onError && (!isSimilar(prevErrors, nextErrors) || !isSimilar(prevWarnings, nextWarnings))) {
228-
onError(nextErrors, nextWarnings);
229-
}
230-
this.errors = nextErrors;
231-
this.warnings = nextWarnings;
232-
}
218+
public triggerMetaEvent = () => {
219+
const { onMetaChange } = this.props;
220+
221+
onMetaChange?.(this.getMeta());
222+
};
233223

234224
// ========================= Field Entity Interfaces =========================
235225
// Trigger by store update. Check if need update the component
@@ -242,15 +232,14 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
242232

243233
const namePathMatch = namePathList && containsNamePath(namePathList, namePath);
244234

245-
const prevErrors = this.errors;
246-
const prevWarnings = this.warnings;
247-
248235
// `setFieldsValue` is a quick access to update related status
249236
if (info.type === 'valueUpdate' && info.source === 'external' && prevValue !== curValue) {
250237
this.touched = true;
251238
this.dirty = true;
252239
this.validatePromise = null;
253-
this.updateError(prevErrors, EMPTY_ERRORS, prevWarnings, EMPTY_ERRORS);
240+
this.errors = EMPTY_ERRORS;
241+
this.warnings = EMPTY_ERRORS;
242+
this.triggerMetaEvent();
254243
}
255244

256245
switch (info.type) {
@@ -260,7 +249,9 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
260249
this.touched = false;
261250
this.dirty = false;
262251
this.validatePromise = null;
263-
this.updateError(prevErrors, EMPTY_ERRORS, prevWarnings, EMPTY_ERRORS);
252+
this.errors = EMPTY_ERRORS;
253+
this.warnings = EMPTY_ERRORS;
254+
this.triggerMetaEvent();
264255

265256
onReset?.();
266257

@@ -272,22 +263,23 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
272263
case 'setField': {
273264
if (namePathMatch) {
274265
const { data } = info;
266+
275267
if ('touched' in data) {
276268
this.touched = data.touched;
277269
}
278270
if ('validating' in data && !('originRCField' in data)) {
279271
this.validatePromise = data.validating ? Promise.resolve([]) : null;
280272
}
281-
282-
const hasError = 'errors' in data;
283-
const hasWarning = 'warnings' in data;
284-
if (hasError || hasWarning) {
285-
const nextErrors = hasError ? data.errors || EMPTY_ERRORS : prevErrors;
286-
const nextWarnings = hasWarning ? data.warnings || EMPTY_ERRORS : prevWarnings;
287-
this.updateError(prevErrors, nextErrors, prevWarnings, nextWarnings);
273+
if ('errors' in data) {
274+
this.errors = data.errors || EMPTY_ERRORS;
275+
}
276+
if ('warnings' in data) {
277+
this.warnings = data.warnings || EMPTY_ERRORS;
288278
}
289279
this.dirty = true;
290280

281+
this.triggerMetaEvent();
282+
291283
this.reRender();
292284
return;
293285
}
@@ -347,9 +339,6 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
347339
};
348340

349341
public validateRules = (options?: ValidateOptions): Promise<RuleError[]> => {
350-
const prevErrors = this.errors;
351-
const prevWarnings = this.warnings;
352-
353342
// We should fixed namePath & value to avoid developer change then by form function
354343
const namePath = this.getNamePath();
355344
const currentValue = this.getValue();
@@ -401,7 +390,9 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
401390
}
402391
});
403392

404-
this.updateError(prevErrors, nextErrors, prevWarnings, nextWarnings);
393+
this.errors = nextErrors;
394+
this.warnings = nextWarnings;
395+
this.triggerMetaEvent();
405396

406397
this.reRender();
407398
}
@@ -414,6 +405,7 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
414405
this.dirty = true;
415406
this.errors = EMPTY_ERRORS;
416407
this.warnings = EMPTY_ERRORS;
408+
this.triggerMetaEvent();
417409

418410
// Force trigger re-render since we need sync renderProps with new meta
419411
this.reRender();
@@ -519,6 +511,8 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
519511
this.touched = true;
520512
this.dirty = true;
521513

514+
this.triggerMetaEvent();
515+
522516
let newValue: StoreValue;
523517
if (getValueFromEvent) {
524518
newValue = getValueFromEvent(...args);

tests/index.test.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ describe('Form.Basic', () => {
101101
it(name, async () => {
102102
let form;
103103
const onReset = jest.fn();
104-
const onError = jest.fn();
104+
const onMeta = jest.fn();
105105

106106
const wrapper = mount(
107107
<div>
@@ -114,7 +114,7 @@ describe('Form.Basic', () => {
114114
name="username"
115115
rules={[{ required: true }]}
116116
onReset={onReset}
117-
onError={onError}
117+
onMetaChange={onMeta}
118118
>
119119
<Input />
120120
</Field>
@@ -126,32 +126,58 @@ describe('Form.Basic', () => {
126126
expect(form.getFieldValue('username')).toEqual('Bamboo');
127127
expect(form.getFieldError('username')).toEqual([]);
128128
expect(form.isFieldTouched('username')).toBeTruthy();
129-
expect(onError).not.toHaveBeenCalled();
129+
expect(onMeta).toHaveBeenCalledWith(
130+
expect.objectContaining({
131+
touched: true,
132+
errors: [],
133+
warnings: [],
134+
}),
135+
);
130136
expect(onReset).not.toHaveBeenCalled();
137+
onMeta.mockRestore();
138+
onReset.mockRestore();
131139

132140
form.resetFields(...args);
133141
expect(form.getFieldValue('username')).toEqual(undefined);
134142
expect(form.getFieldError('username')).toEqual([]);
135143
expect(form.isFieldTouched('username')).toBeFalsy();
136-
expect(onError).not.toHaveBeenCalled();
144+
expect(onMeta).toHaveBeenCalledWith(
145+
expect.objectContaining({
146+
touched: false,
147+
errors: [],
148+
warnings: [],
149+
}),
150+
);
137151
expect(onReset).toHaveBeenCalled();
138-
onError.mockRestore();
152+
onMeta.mockRestore();
139153
onReset.mockRestore();
140154

141155
await changeValue(getField(wrapper, 'username'), '');
142156
expect(form.getFieldValue('username')).toEqual('');
143157
expect(form.getFieldError('username')).toEqual(["'username' is required"]);
144158
expect(form.isFieldTouched('username')).toBeTruthy();
145-
expect(onError).toHaveBeenCalledWith(["'username' is required"], []);
159+
expect(onMeta).toHaveBeenCalledWith(
160+
expect.objectContaining({
161+
touched: true,
162+
errors: ["'username' is required"],
163+
warnings: [],
164+
}),
165+
);
146166
expect(onReset).not.toHaveBeenCalled();
147-
onError.mockRestore();
167+
onMeta.mockRestore();
148168
onReset.mockRestore();
149169

150170
form.resetFields(...args);
151171
expect(form.getFieldValue('username')).toEqual(undefined);
152172
expect(form.getFieldError('username')).toEqual([]);
153173
expect(form.isFieldTouched('username')).toBeFalsy();
154-
expect(onError).toHaveBeenCalledWith([], []);
174+
expect(onMeta).toHaveBeenCalledWith(
175+
expect.objectContaining({
176+
touched: false,
177+
errors: [],
178+
warnings: [],
179+
}),
180+
);
155181
expect(onReset).toHaveBeenCalled();
156182
});
157183
}

0 commit comments

Comments
 (0)