diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c12ad5de..f060cb5040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ should change the heading of the (upcoming) version to include a major version b # v4.0.2 (upcoming) +## @rjsf/core + +- To improve performance, skip validating subschemas in oneOf / anyOf if formData is undefined (#2676) + # v4.0.1 - Bumped the peer dependencies of `@rjsf/core` to `^4.0.0` for all of themes in `package.json` diff --git a/packages/core/src/utils.js b/packages/core/src/utils.js index 3bc1bdbc29..14efe21bdf 100644 --- a/packages/core/src/utils.js +++ b/packages/core/src/utils.js @@ -1244,6 +1244,11 @@ export function rangeSpec(schema) { } export function getMatchingOption(formData, options, rootSchema) { + // For performance, skip validating subschemas if formData is undefined. We just + // want to get the first option in that case. + if (formData === undefined) { + return 0; + } for (let i = 0; i < options.length; i++) { const option = options[i]; diff --git a/packages/core/test/utils_test.js b/packages/core/test/utils_test.js index ba6c918045..e12b7808ab 100644 --- a/packages/core/test/utils_test.js +++ b/packages/core/test/utils_test.js @@ -4200,6 +4200,55 @@ describe("utils", () => { })) ); }); + it("should infer correct anyOf schema based on data if passing undefined", () => { + const rootSchema = { + defs: { + a: { type: "object", properties: { id: { enum: ["a"] } } }, + nested: { + type: "object", + properties: { + id: { enum: ["nested"] }, + child: { $ref: "#/defs/any" }, + }, + }, + any: { anyOf: [{ $ref: "#/defs/a" }, { $ref: "#/defs/nested" }] }, + }, + $ref: "#/defs/any", + }; + const options = [ + { type: "object", properties: { id: { enum: ["a"] } } }, + { + type: "object", + properties: { + id: { enum: ["nested"] }, + child: { $ref: "#/defs/any" }, + }, + }, + ]; + expect(getMatchingOption(undefined, options, rootSchema)).eql(0); + }); + it("should infer correct anyOf schema based on data if passing null and option 2 is {type: null}", () => { + const rootSchema = { + defs: { + a: { type: "object", properties: { id: { enum: ["a"] } } }, + nested: { + type: "object", + properties: { + id: { enum: ["nested"] }, + child: { $ref: "#/defs/any" }, + }, + }, + any: { anyOf: [{ $ref: "#/defs/a" }, { $ref: "#/defs/nested" }] }, + }, + $ref: "#/defs/any", + }; + const options = [ + { type: "string" }, + { type: "string" }, + { type: "null" }, + ]; + expect(getMatchingOption(null, options, rootSchema)).eql(2); + }); it("should infer correct anyOf schema based on data", () => { const rootSchema = { defs: {