Skip to content

Commit

Permalink
refactor: form.jsx is no longer using componentwillreceiveprops
Browse files Browse the repository at this point in the history
  • Loading branch information
Jimmy Callin committed Aug 23, 2020
1 parent 93330f6 commit a9d8e05
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 139 deletions.
6 changes: 3 additions & 3 deletions packages/antd/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

163 changes: 28 additions & 135 deletions packages/core/src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import _isEmpty from "lodash/isEmpty";

import { default as DefaultErrorList } from "./ErrorList";
import {
getDefaultFormState,
retrieveSchema,
shouldRender,
toIdSchema,
getDefaultRegistry,
deepEquals,
toPathSchema,
isObject,
getRegistry,
validate,
getStateFromProps,
} from "../utils";
import validateFormData, { toErrorList } from "../validate";
import { toErrorList } from "../validate";
import { mergeObjects } from "../utils";

function handleChange(props, state) {
const { lastProps, ...formState } = state;
props.onChange(formState);
}

export default class Form extends Component {
static defaultProps = {
uiSchema: {},
Expand All @@ -31,134 +36,38 @@ export default class Form extends Component {

constructor(props) {
super(props);
this.state = this.getStateFromProps(props, props.formData);
this.state = getStateFromProps(props, props.formData);
}

formElement = null;

componentDidMount() {
if (
this.props.onChange &&
!deepEquals(this.state.formData, this.props.formData)
) {
this.props.onChange(this.state);
handleChange(this.props, this.state);
}
this.formElement = null;
}

UNSAFE_componentWillReceiveProps(nextProps) {
const nextState = this.getStateFromProps(nextProps, nextProps.formData);
componentDidUpdate(prevProps) {
if (
!deepEquals(nextState.formData, nextProps.formData) &&
!deepEquals(nextState.formData, this.state.formData) &&
this.props.onChange
this.props.onChange &&
!deepEquals(this.state.formData, this.props.formData)
) {
this.props.onChange(nextState);
handleChange(this.props, this.state);
}
this.setState(nextState);
}

getStateFromProps(props, inputFormData) {
const state = this.state || {};
const schema = "schema" in props ? props.schema : this.props.schema;
const uiSchema = "uiSchema" in props ? props.uiSchema : this.props.uiSchema;
const edit = typeof inputFormData !== "undefined";
const liveValidate =
"liveValidate" in props ? props.liveValidate : this.props.liveValidate;
const mustValidate = edit && !props.noValidate && liveValidate;
const rootSchema = schema;
const formData = getDefaultFormState(schema, inputFormData, rootSchema);
const retrievedSchema = retrieveSchema(schema, rootSchema, formData);
const customFormats = props.customFormats;
const additionalMetaSchemas = props.additionalMetaSchemas;

const getCurrentErrors = () => {
if (props.noValidate) {
return { errors: [], errorSchema: {} };
} else if (!props.liveValidate) {
return {
errors: state.schemaValidationErrors || [],
errorSchema: state.schemaValidationErrorSchema || {},
};
}
return {
errors: state.errors || [],
errorSchema: state.errorSchema || {},
};
};

let errors,
errorSchema,
schemaValidationErrors,
schemaValidationErrorSchema;
if (mustValidate) {
const schemaValidation = this.validate(
formData,
schema,
additionalMetaSchemas,
customFormats
);
errors = schemaValidation.errors;
errorSchema = schemaValidation.errorSchema;
schemaValidationErrors = errors;
schemaValidationErrorSchema = errorSchema;
} else {
const currentErrors = getCurrentErrors();
errors = currentErrors.errors;
errorSchema = currentErrors.errorSchema;
schemaValidationErrors = state.schemaValidationErrors;
schemaValidationErrorSchema = state.schemaValidationErrorSchema;
}
if (props.extraErrors) {
errorSchema = mergeObjects(
errorSchema,
props.extraErrors,
!!"concat arrays"
);
errors = toErrorList(errorSchema);
}
const idSchema = toIdSchema(
retrievedSchema,
uiSchema["ui:rootFieldId"],
rootSchema,
formData,
props.idPrefix
);
const nextState = {
schema,
uiSchema,
idSchema,
formData,
edit,
errors,
errorSchema,
additionalMetaSchemas,
};
if (schemaValidationErrors) {
nextState.schemaValidationErrors = schemaValidationErrors;
nextState.schemaValidationErrorSchema = schemaValidationErrorSchema;
static getDerivedStateFromProps(props, state) {
if (!deepEquals(state.lastProps, props)) {
return getStateFromProps(props, props.formData, state);
}
return nextState;
}

shouldComponentUpdate(nextProps, nextState) {
return shouldRender(this, nextProps, nextState);
}

validate(
formData,
schema = this.props.schema,
additionalMetaSchemas = this.props.additionalMetaSchemas,
customFormats = this.props.customFormats
) {
const { validate, transformErrors } = this.props;
const { rootSchema } = this.getRegistry();
const resolvedSchema = retrieveSchema(schema, rootSchema, formData);
return validateFormData(
formData,
resolvedSchema,
validate,
transformErrors,
additionalMetaSchemas,
customFormats
);
}

renderErrors() {
const { errors, errorSchema, schema, uiSchema } = this.state;
const { ErrorList, showErrorList, formContext } = this.props;
Expand Down Expand Up @@ -222,7 +131,7 @@ export default class Form extends Component {

onChange = (formData, newErrorSchema) => {
if (isObject(formData) || Array.isArray(formData)) {
const newState = this.getStateFromProps(this.props, formData);
const newState = getStateFromProps(this.props, formData, this.state);
formData = newState.formData;
}
const mustValidate = !this.props.noValidate && this.props.liveValidate;
Expand Down Expand Up @@ -251,7 +160,7 @@ export default class Form extends Component {
}

if (mustValidate) {
let schemaValidation = this.validate(newFormData);
let schemaValidation = validate(newFormData, this.props);
let errors = schemaValidation.errors;
let errorSchema = schemaValidation.errorSchema;
const schemaValidationErrors = errors;
Expand Down Expand Up @@ -287,7 +196,7 @@ export default class Form extends Component {
}
this.setState(
state,
() => this.props.onChange && this.props.onChange(this.state)
() => this.props.onChange && handleChange(this.props, this.state)
);
};

Expand Down Expand Up @@ -331,7 +240,7 @@ export default class Form extends Component {
}

if (!this.props.noValidate) {
let schemaValidation = this.validate(newFormData);
let schemaValidation = validate(newFormData, this.props);
let errors = schemaValidation.errors;
let errorSchema = schemaValidation.errorSchema;
const schemaValidationErrors = errors;
Expand Down Expand Up @@ -387,22 +296,6 @@ export default class Form extends Component {
);
};

getRegistry() {
// For BC, accept passed SchemaField and TitleField props and pass them to
// the "fields" registry one.
const { fields, widgets } = getDefaultRegistry();
return {
fields: { ...fields, ...this.props.fields },
widgets: { ...widgets, ...this.props.widgets },
ArrayFieldTemplate: this.props.ArrayFieldTemplate,
ObjectFieldTemplate: this.props.ObjectFieldTemplate,
FieldTemplate: this.props.FieldTemplate,
definitions: this.props.schema.definitions || {},
rootSchema: this.props.schema,
formContext: this.props.formContext || {},
};
}

submit() {
if (this.formElement) {
this.formElement.dispatchEvent(
Expand Down Expand Up @@ -434,7 +327,7 @@ export default class Form extends Component {
} = this.props;

const { schema, uiSchema, formData, errorSchema, idSchema } = this.state;
const registry = this.getRegistry();
const registry = getRegistry(this.props);
const _SchemaField = registry.fields.SchemaField;
const FormTag = tagName ? tagName : "form";
if (deprecatedAutocomplete) {
Expand Down
114 changes: 113 additions & 1 deletion packages/core/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import * as ReactIs from "react-is";
import mergeAllOf from "json-schema-merge-allof";
import fill from "core-js/library/fn/array/fill";
import validateFormData, { isValid } from "./validate";
import validateFormData, { isValid, toErrorList } from "./validate";
import union from "lodash/union";
import jsonpointer from "jsonpointer";

Expand Down Expand Up @@ -1243,3 +1243,115 @@ export function schemaRequiresTrueValue(schema) {

return false;
}

export function getRegistry(props) {
const { fields, widgets } = getDefaultRegistry();
return {
fields: { ...fields, ...props.fields },
widgets: { ...widgets, ...props.widgets },
ArrayFieldTemplate: props.ArrayFieldTemplate,
ObjectFieldTemplate: props.ObjectFieldTemplate,
FieldTemplate: props.FieldTemplate,
definitions: props.schema.definitions || {},
rootSchema: props.schema,
formContext: props.formContext || {},
};
}

export function validate(
formData,
props,
schema = props.schema,
additionalMetaSchemas = props.additionalMetaSchemas,
customFormats = props.customFormats
) {
const { validate, transformErrors } = props;
const { rootSchema } = getRegistry(props);
const resolvedSchema = retrieveSchema(schema, rootSchema, formData);
return validateFormData(
formData,
resolvedSchema,
validate,
transformErrors,
additionalMetaSchemas,
customFormats
);
}

export function getStateFromProps(props, inputFormData, state = {}) {
const edit = typeof inputFormData !== "undefined";
const mustValidate = edit && !props.noValidate && props.liveValidate;
const formData = getDefaultFormState(
props.schema,
inputFormData,
props.schema
);
const retrievedSchema = retrieveSchema(props.schema, props.schema, formData);

const getCurrentErrors = () => {
if (props.noValidate) {
return { errors: [], errorSchema: {} };
} else if (!props.liveValidate) {
return {
errors: state.schemaValidationErrors || [],
errorSchema: state.schemaValidationErrorSchema || {},
};
}
return {
errors: state.errors || [],
errorSchema: state.errorSchema || {},
};
};

let errors, errorSchema, schemaValidationErrors, schemaValidationErrorSchema;
if (mustValidate) {
const schemaValidation = validate(
formData,
props,
props.schema,
props.additionalMetaSchemas,
props.customFormats
);
errors = schemaValidation.errors;
errorSchema = schemaValidation.errorSchema;
schemaValidationErrors = errors;
schemaValidationErrorSchema = errorSchema;
} else {
const currentErrors = getCurrentErrors();
errors = currentErrors.errors;
errorSchema = currentErrors.errorSchema;
schemaValidationErrors = state.schemaValidationErrors;
schemaValidationErrorSchema = state.schemaValidationErrorSchema;
}
if (props.extraErrors) {
errorSchema = mergeObjects(
errorSchema,
props.extraErrors,
!!"concat arrays"
);
errors = toErrorList(errorSchema);
}
const idSchema = toIdSchema(
retrievedSchema,
props.uiSchema["ui:rootFieldId"],
props.schema,
formData,
props.idPrefix
);
const nextState = {
schema: props.schema,
uiSchema: props.uiSchema,
idSchema,
formData,
edit,
errors,
errorSchema,
additionalMetaSchemas: props.additionalMetaSchemas,
lastProps: props,
};
if (schemaValidationErrors) {
nextState.schemaValidationErrors = schemaValidationErrors;
nextState.schemaValidationErrorSchema = schemaValidationErrorSchema;
}
return nextState;
}

0 comments on commit a9d8e05

Please sign in to comment.