Skip to content

Commit

Permalink
fix: formData change clear errorMessage
Browse files Browse the repository at this point in the history
fix: merge errorSchema

fix: merge errorSchema
  • Loading branch information
JinYuSha0 committed Dec 20, 2024
1 parent 5335d72 commit d4faff8
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
22 changes: 19 additions & 3 deletions packages/core/src/components/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ErrorTransformer,
FormContextType,
GenericObjectType,
getChangedFields,
getTemplate,
getUiOptions,
IdSchema,
Expand Down Expand Up @@ -316,16 +317,18 @@ export default class Form<
prevState: FormState<T, S, F>
): { nextState: FormState<T, S, F>; shouldUpdate: true } | { shouldUpdate: false } {
if (!deepEquals(this.props, prevProps)) {
const formDataChangedFields = getChangedFields(this.props.formData, prevProps.formData);
const isSchemaChanged = !deepEquals(prevProps.schema, this.props.schema);
const isFormDataChanged = !deepEquals(prevProps.formData, this.props.formData);
const isFormDataChanged = formDataChangedFields.length > 0;
const nextState = this.getStateFromProps(
this.props,
this.props.formData,
// If the `schema` has changed, we need to update the retrieved schema.
// Or if the `formData` changes, for example in the case of a schema with dependencies that need to
// match one of the subSchemas, the retrieved schema must be updated.
isSchemaChanged || isFormDataChanged ? undefined : this.state.retrievedSchema,
isSchemaChanged
isSchemaChanged,
formDataChangedFields
);
const shouldUpdate = !deepEquals(nextState, prevState);
return { nextState, shouldUpdate };
Expand Down Expand Up @@ -375,13 +378,15 @@ export default class Form<
* @param inputFormData - The new or current data for the `Form`
* @param retrievedSchema - An expanded schema, if not provided, it will be retrieved from the `schema` and `formData`.
* @param isSchemaChanged - A flag indicating whether the schema has changed.
* @param formDataChangedFields - The changed fields of `formData`
* @returns - The new state for the `Form`
*/
getStateFromProps(
props: FormProps<T, S, F>,
inputFormData?: T,
retrievedSchema?: S,
isSchemaChanged = false
isSchemaChanged = false,
formDataChangedFields: string[] = []
): FormState<T, S, F> {
const state: FormState<T, S, F> = this.state || {};
const schema = 'schema' in props ? props.schema : this.props.schema;
Expand Down Expand Up @@ -458,6 +463,17 @@ export default class Form<
const currentErrors = getCurrentErrors();
errors = currentErrors.errors;
errorSchema = currentErrors.errorSchema;
if (formDataChangedFields.length > 0) {
const newErrorSchema = formDataChangedFields.reduce((acc, key) => {
acc[key] = undefined;
return acc;
}, {} as Record<string, undefined>);
errorSchema = schemaValidationErrorSchema = mergeObjects(
currentErrors.errorSchema,
newErrorSchema,
'preventDuplicates'
) as ErrorSchema<T>;
}
}
if (props.extraErrors) {
const merged = validationDataMerge({ errorSchema, errors }, props.extraErrors);
Expand Down
23 changes: 23 additions & 0 deletions packages/utils/src/getChangedFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import keys from 'lodash/keys';
import pickBy from 'lodash/pickBy';
import isEqual from 'lodash/isEqual';

/**
* Compares two objects and returns the names of the fields that have changed.
* This function iterates over each field of object `a`, using `_.isEqual` to compare the field value
* with the corresponding field value in object `b`. If the values are different, the field name will
* be included in the returned array.
*
* @param {any} a - The first object, representing the original data to compare.
* @param {any} b - The second object, representing the updated data to compare.
* @returns {string[]} - An array of field names that have changed.
*
* @example
* const a = { name: 'John', age: 30 };
* const b = { name: 'John', age: 31 };
* const changedFields = getChangedFields(a, b);
* console.log(changedFields); // Output: ['age']
*/
export default function getChangedFields(a: any, b: any): string[] {
return keys(pickBy(a, (value, key) => !isEqual(value, b[key])));
}
2 changes: 2 additions & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import utcToLocal from './utcToLocal';
import validationDataMerge from './validationDataMerge';
import withIdRefPrefix from './withIdRefPrefix';
import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';
import getChangedFields from './getChangedFields';

export * from './types';
export * from './enums';
Expand Down Expand Up @@ -82,6 +83,7 @@ export {
examplesId,
ErrorSchemaBuilder,
findSchemaDefinition,
getChangedFields,
getDateElementProps,
getDiscriminatorFieldFromSchema,
getInputProps,
Expand Down

0 comments on commit d4faff8

Please sign in to comment.