Skip to content

Commit e7d2765

Browse files
Fix 4821 by no saving undefined values into an object for a null type field (#4839)
* Fix 4821 by no saving undefined values into an object for a null type field Fixed #4821 by not saving an undefined field value into an object when that field has the `null` type - Updated `getDefaultFormState()` to not save an undefined field value into an object when the type is `null` and `excludeObjectChildren` is provided - Updated the tests to verify this new fix - Updated the `CHANGELOG.md` accordingly # Conflicts: # CHANGELOG.md * - Responded to reviewer feedback
1 parent ba969ae commit e7d2765

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ should change the heading of the (upcoming) version to include a major version b
6060

6161
- Updated `FieldTemplate` to skip label and description rendering for checkbox widgets, fixing ([#4742](https://github.com/rjsf-team/react-jsonschema-form/issues/4742))
6262

63+
## @rjsf/utils
64+
65+
- Updated `getDefaultFormState()` to not save an undefined field value into an object when the type is `null` and `excludeObjectChildren` is provided, fixing [#4821](https://github.com/rjsf-team/react-jsonschema-form/issues/4821)
66+
6367
## Dev / docs / playground
6468

6569
- Updated the `OptionsDrawer` of the playground to add `idPrefix` and `idSeparator` fields

packages/utils/src/schema/getDefaultFormState.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export function computeDefaultBasedOnSchemaTypeAndDefaults<T = any, S extends St
121121
* @param experimental_defaultFormStateBehavior - Optional configuration object, if provided, allows users to override
122122
* default form state behavior
123123
* @param isConst - Optional flag, if true, indicates that the schema has a const property defined, thus we should always return the computedDefault since it's coming from the const.
124+
* @param isNullType - The type of the schema is null
124125
*/
125126
function maybeAddDefaultToObject<T = any>(
126127
obj: GenericObjectType,
@@ -131,6 +132,7 @@ function maybeAddDefaultToObject<T = any>(
131132
requiredFields: string[] = [],
132133
experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior = {},
133134
isConst = false,
135+
isNullType = false,
134136
) {
135137
const { emptyObjectFields = 'populateAllDefaults' } = experimental_defaultFormStateBehavior;
136138

@@ -141,7 +143,7 @@ function maybeAddDefaultToObject<T = any>(
141143
} else if (includeUndefinedValues === 'excludeObjectChildren') {
142144
// Fix for Issue #4709: When in 'excludeObjectChildren' mode, don't set primitive fields to empty objects
143145
// Only add the computed default if it's not an empty object placeholder for a primitive field
144-
if (!isObject(computedDefault) || !isEmpty(computedDefault)) {
146+
if ((isNullType && computedDefault !== undefined) || !isObject(computedDefault) || !isEmpty(computedDefault)) {
145147
obj[key] = computedDefault;
146148
}
147149
// If computedDefault is an empty object {}, don't add it - let the field stay undefined
@@ -517,6 +519,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
517519
retrievedSchema.required,
518520
experimental_defaultFormStateBehavior,
519521
hasConst,
522+
propertySchema?.type === 'null',
520523
);
521524

522525
return acc;

packages/utils/test/schema/getDefaultFormStateTest.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,53 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
376376
});
377377
});
378378

379+
describe("an object with an null-type property and includeUndefinedValues is 'excludeObjectChildren'", () => {
380+
const schema: RJSFSchema = {
381+
type: 'object',
382+
properties: {
383+
optionalNullProperty: {
384+
type: 'null',
385+
},
386+
requiredProperty: {
387+
type: 'string',
388+
default: 'foo',
389+
},
390+
},
391+
required: ['requiredProperty'],
392+
};
393+
const includeUndefinedValues = 'excludeObjectChildren';
394+
const expected = {
395+
requiredProperty: 'foo',
396+
};
397+
398+
test('getDefaultFormState', () => {
399+
expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual(
400+
expected,
401+
);
402+
});
403+
404+
test('computeDefaults', () => {
405+
expect(
406+
computeDefaults(testValidator, schema, {
407+
rootSchema: schema,
408+
includeUndefinedValues,
409+
}),
410+
).toEqual(expected);
411+
});
412+
413+
test('getDefaultBasedOnSchemaType', () => {
414+
expect(
415+
getDefaultBasedOnSchemaType(testValidator, schema, { rootSchema: schema, includeUndefinedValues }),
416+
).toEqual(expected);
417+
});
418+
419+
test('getObjectDefaults', () => {
420+
expect(getObjectDefaults(testValidator, schema, { rootSchema: schema, includeUndefinedValues })).toEqual(
421+
expected,
422+
);
423+
});
424+
});
425+
379426
describe('an object with an additionalProperties', () => {
380427
const schema: RJSFSchema = {
381428
type: 'object',

0 commit comments

Comments
 (0)