Skip to content

Commit

Permalink
use fast-deep-equal
Browse files Browse the repository at this point in the history
  • Loading branch information
igorbrasileiro committed Sep 5, 2024
1 parent 6ca6edd commit 6ba3bdf
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 31 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@
"packages/validator-ajv6",
"packages/validator-ajv8",
"packages/snapshot-tests"
]
],
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
52 changes: 36 additions & 16 deletions packages/core/src/components/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Component, ElementType, FormEvent, ReactNode, Ref, RefObject, createRef } from 'react';
import { Component, createRef, ElementType, FormEvent, ReactNode, Ref, RefObject } from 'react';
import {
createSchemaUtils,
CustomValidator,
deepEquals,
ErrorSchema,
ErrorTransformer,
Experimental_DefaultFormStateBehavior,
FormContextType,
GenericObjectType,
getTemplate,
Expand All @@ -14,31 +15,31 @@ import {
mergeObjects,
NAME_KEY,
PathSchema,
StrictRJSFSchema,
Registry,
RegistryFieldsType,
RegistryWidgetsType,
RJSF_ADDITIONAL_PROPERTIES_FLAG,
RJSFSchema,
RJSFValidationError,
RJSF_ADDITIONAL_PROPERTIES_FLAG,
SchemaUtilsType,
shouldRender,
StrictRJSFSchema,
SUBMIT_BTN_OPTIONS_KEY,
TemplatesType,
toErrorList,
UiSchema,
UI_GLOBAL_OPTIONS_KEY,
UI_OPTIONS_KEY,
UiSchema,
ValidationData,
validationDataMerge,
ValidatorType,
Experimental_DefaultFormStateBehavior,
} from '@rjsf/utils';
import _forEach from 'lodash/forEach';
import _get from 'lodash/get';
import _isEmpty from 'lodash/isEmpty';
import _pick from 'lodash/pick';
import _toPath from 'lodash/toPath';
import fastDeepEqual from 'fast-deep-equal';

import getDefaultRegistry from '../getDefaultRegistry';

Expand Down Expand Up @@ -282,7 +283,7 @@ export default class Form<
}

this.state = this.getStateFromProps(props, props.formData);
if (this.props.onChange && !deepEquals(this.state.formData, this.props.formData)) {
if (this.props.onChange && !fastDeepEqual(this.state.formData, this.props.formData)) {
this.props.onChange(this.state);
}
this.formElement = createRef();
Expand All @@ -309,10 +310,14 @@ export default class Form<
getSnapshotBeforeUpdate(
prevProps: FormProps<T, S, F>,
prevState: FormState<T, S, F>
): { nextState: FormState<T, S, F>; shouldUpdate: true } | { shouldUpdate: false } {
):
| { nextState: FormState<T, S, F>; shouldUpdate: true }
| {
shouldUpdate: false;
} {
if (!deepEquals(this.props, prevProps)) {
const isSchemaChanged = !deepEquals(prevProps.schema, this.props.schema);
const isFormDataChanged = !deepEquals(prevProps.formData, this.props.formData);
const isSchemaChanged = !fastDeepEqual(prevProps.schema, this.props.schema);
const isFormDataChanged = !fastDeepEqual(prevProps.formData, this.props.formData);
const nextState = this.getStateFromProps(
this.props,
this.props.formData,
Expand Down Expand Up @@ -346,14 +351,18 @@ export default class Form<
componentDidUpdate(
_: FormProps<T, S, F>,
prevState: FormState<T, S, F>,
snapshot: { nextState: FormState<T, S, F>; shouldUpdate: true } | { shouldUpdate: false }
snapshot:
| { nextState: FormState<T, S, F>; shouldUpdate: true }
| {
shouldUpdate: false;
}
) {
if (snapshot.shouldUpdate) {
const { nextState } = snapshot;

if (
!deepEquals(nextState.formData, this.props.formData) &&
!deepEquals(nextState.formData, prevState.formData) &&
!fastDeepEqual(nextState.formData, this.props.formData) &&
!fastDeepEqual(nextState.formData, prevState.formData) &&
this.props.onChange
) {
this.props.onChange(nextState);
Expand Down Expand Up @@ -692,7 +701,6 @@ export default class Form<
* Callback function to handle reset form data.
* - Reset all fields with default values.
* - Reset validations and errors
*
*/
reset = () => {
const { onChange } = this.props;
Expand Down Expand Up @@ -772,7 +780,14 @@ export default class Form<
},
() => {
if (onSubmit) {
onSubmit({ ...this.state, formData: newFormData, status: 'submitted' }, event);
onSubmit(
{
...this.state,
formData: newFormData,
status: 'submitted',
},
event
);
}
}
);
Expand Down Expand Up @@ -956,9 +971,14 @@ export default class Form<

let { [SUBMIT_BTN_OPTIONS_KEY]: submitOptions = {} } = getUiOptions<T, S, F>(uiSchema);
if (disabled) {
submitOptions = { ...submitOptions, props: { ...submitOptions.props, disabled: true } };
submitOptions = {
...submitOptions,
props: { ...submitOptions.props, disabled: true },
};
}
const submitUiSchema = { [UI_OPTIONS_KEY]: { [SUBMIT_BTN_OPTIONS_KEY]: submitOptions } };
const submitUiSchema = {
[UI_OPTIONS_KEY]: { [SUBMIT_BTN_OPTIONS_KEY]: submitOptions },
};

return (
<FormTag
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/fields/MultiSchemaField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import isEmpty from 'lodash/isEmpty';
import omit from 'lodash/omit';
import {
ANY_OF_KEY,
deepEquals,
ERRORS_KEY,
FieldProps,
FormContextType,
Expand All @@ -18,6 +17,7 @@ import {
TranslatableString,
UiSchema,
} from '@rjsf/utils';
import fastDeepEqual from 'fast-deep-equal';

/** Type used for the state of the `AnyOfField` component */
type AnyOfFieldState<S extends StrictRJSFSchema = RJSFSchema> = {
Expand Down Expand Up @@ -67,15 +67,15 @@ class AnyOfField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends For
const { formData, options, idSchema } = this.props;
const { selectedOption } = this.state;
let newState = this.state;
if (!deepEquals(prevProps.options, options)) {
if (!fastDeepEqual(prevProps.options, options)) {
const {
registry: { schemaUtils },
} = this.props;
// re-cache the retrieved options in state in case they have $refs to save doing it later
const retrievedOptions = options.map((opt: S) => schemaUtils.retrieveSchema(opt, formData));
newState = { selectedOption, retrievedOptions };
}
if (!deepEquals(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
if (!fastDeepEqual(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
const { retrievedOptions } = newState;
const matchingOption = this.getMatchingOption(selectedOption, formData, retrievedOptions);

Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/enumOptionsDeselectValue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';

import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
import enumOptionsValueForIndex from './enumOptionsValueForIndex';
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/enumOptionsIsSelected.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';

import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';

Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/parser/ParserValidator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';

import { ID_KEY } from '../constants';
import hashForSchema from '../hashForSchema';
Expand Down
6 changes: 3 additions & 3 deletions packages/utils/src/parser/schemaParser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import forEach from 'lodash/forEach';
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';

import { FormContextType, RJSFSchema, StrictRJSFSchema } from '../types';
import { PROPERTIES_KEY, ITEMS_KEY } from '../constants';
import { ITEMS_KEY, PROPERTIES_KEY } from '../constants';
import ParserValidator, { SchemaMap } from './ParserValidator';
import { retrieveSchemaInternal, resolveAnyOrOneOfSchemas } from '../schema/retrieveSchema';
import { resolveAnyOrOneOfSchemas, retrieveSchemaInternal } from '../schema/retrieveSchema';

/** Recursive function used to parse the given `schema` belonging to the `rootSchema`. The `validator` is used to
* capture the sub-schemas that the `isValid()` function is called with. For each schema returned by the
Expand Down
11 changes: 7 additions & 4 deletions packages/utils/src/schema/retrieveSchema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';
import set from 'lodash/set';
import times from 'lodash/times';
import transform from 'lodash/transform';
Expand All @@ -15,10 +15,10 @@ import {
ANY_OF_KEY,
DEPENDENCIES_KEY,
IF_KEY,
ITEMS_KEY,
ONE_OF_KEY,
REF_KEY,
PROPERTIES_KEY,
ITEMS_KEY,
REF_KEY,
} from '../constants';
import findSchemaDefinition, { splitKeyElementFromObject } from '../findSchemaDefinition';
import getDiscriminatorFieldFromSchema from '../getDiscriminatorFieldFromSchema';
Expand Down Expand Up @@ -196,7 +196,10 @@ export function resolveSchema<T = any, S extends StrictRJSFSchema = RJSFSchema,
)
);
const allPermutations = getAllPermutationsOfXxxOf<S>(allOfSchemaElements);
return allPermutations.map((permutation) => ({ ...schema, allOf: permutation }));
return allPermutations.map((permutation) => ({
...schema,
allOf: permutation,
}));
}
// No $ref or dependencies or allOf attribute was found, returning the original schema.
return [schema];
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/schema/toIdSchema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';

import { ALL_OF_KEY, DEPENDENCIES_KEY, ID_KEY, ITEMS_KEY, PROPERTIES_KEY, REF_KEY } from '../constants';
import isObject from '../isObject';
Expand Down

0 comments on commit 6ba3bdf

Please sign in to comment.