Skip to content

Commit bdc063b

Browse files
Fix: Reworked the additional properties remove code (#4852)
Fixes: #4850 by moving the deleting of an additional property from `ObjectField` to `Form` - In `@rjsf/utils` added a special `ADDITIONAL_PROPERTY_KEY_REMOVE` symbol to `constants.ts` - In `@rjsf/core`: - Updated `ObjectField`'s `handleRemoveProperty()` to call `onChange()` with `ADDITIONAL_PROPERTY_KEY_REMOVE` and the `fieldPathId.path` + `key` - Made the `key` for the `ObjectFieldProperty` render stable - Updated `Form`'s `processPendingChange()` to detect when the `newValue` is `ADDITIONAL_PROPERTY_KEY_REMOVE` and remove the data instead. - Updated the `CHANGELOG.md` accordingly
1 parent fd3024d commit bdc063b

File tree

4 files changed

+15
-13
lines changed

4 files changed

+15
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ should change the heading of the (upcoming) version to include a major version b
3232
- Fixed duplicate label and description rendering in `CheckboxWidget` by conditionally rendering them based on widget type
3333
- Updated `CheckboxWidget` to handle label and description rendering consistently
3434
- Modified `FieldTemplate` to skip label and description rendering for checkbox widgets, fixing ([#4742](https://github.com/rjsf-team/react-jsonschema-form/issues/4742))
35+
- Updated `ObjectField` to change the removal of an additional property to defer the work to the `processPendingChange()` handler in `Form`, fixing [#4850](https://github.com/rjsf-team/react-jsonschema-form/issues/4850)
3536

3637
## @rjsf/fluentui-rc
3738

@@ -65,6 +66,7 @@ should change the heading of the (upcoming) version to include a major version b
6566
## @rjsf/utils
6667

6768
- 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)
69+
- Added new `ADDITIONAL_PROPERTY_KEY_REMOVE` constant
6870

6971
## Dev / docs / playground
7072

packages/core/src/components/Form.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, ElementType, FormEvent, ReactNode, Ref, RefObject, createRef } from 'react';
22
import {
3+
ADDITIONAL_PROPERTY_KEY_REMOVE,
34
createSchemaUtils,
45
CustomValidator,
56
deepEquals,
@@ -51,6 +52,7 @@ import _isEmpty from 'lodash/isEmpty';
5152
import _pick from 'lodash/pick';
5253
import _set from 'lodash/set';
5354
import _toPath from 'lodash/toPath';
55+
import _unset from 'lodash/unset';
5456

5557
import getDefaultRegistry from '../getDefaultRegistry';
5658

@@ -875,7 +877,10 @@ export default class Form<
875877
let retrievedSchema = this.state.retrievedSchema;
876878
let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
877879
if (isObject(formData) || Array.isArray(formData)) {
878-
if (!isRootPath) {
880+
if (newValue === ADDITIONAL_PROPERTY_KEY_REMOVE) {
881+
// For additional properties, we were given the special remove this key value, so unset it
882+
_unset(formData, path);
883+
} else if (!isRootPath) {
879884
// If the newValue is not on the root path, then set it into the form data
880885
_set(formData, path, newValue);
881886
}

packages/core/src/components/fields/ObjectField.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { FocusEvent, useCallback, useState } from 'react';
22
import {
3+
ADDITIONAL_PROPERTY_KEY_REMOVE,
34
ADDITIONAL_PROPERTY_FLAG,
45
ANY_OF_KEY,
56
getTemplate,
67
getUiOptions,
7-
hashObject,
88
isFormDataAvailable,
99
orderProperties,
1010
shouldRenderOptionalField,
@@ -29,7 +29,6 @@ import get from 'lodash/get';
2929
import has from 'lodash/has';
3030
import isObject from 'lodash/isObject';
3131
import set from 'lodash/set';
32-
import unset from 'lodash/unset';
3332

3433
/** Returns a flag indicating whether the `name` field is required in the object schema
3534
*
@@ -220,7 +219,6 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
220219
const schema: S = schemaUtils.retrieveSchema(rawSchema, formData, true);
221220
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
222221
const { properties: schemaProperties = {} } = schema;
223-
const formDataHash = hashObject(formData || {});
224222
// All the children will use childFieldPathId if present in the props, falling back to the fieldPathId
225223
const childFieldPathId = props.childFieldPathId ?? fieldPathId;
226224

@@ -320,15 +318,14 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
320318
[formData, onChange, childFieldPathId, getAvailableKey],
321319
);
322320

323-
/** Handles the remove click which removes the old `key` data and calls the `onChange` callback with it
321+
/** Handles the remove click which calls the `onChange` callback with the special ADDITIONAL_PROPERTY_FIELD_REMOVE
322+
* value for the path plus the key to be removed
324323
*/
325324
const handleRemoveProperty = useCallback(
326325
(key: string) => {
327-
const copiedFormData = { ...formData } as T;
328-
unset(copiedFormData, key);
329-
onChange(copiedFormData, childFieldPathId.path);
326+
onChange(ADDITIONAL_PROPERTY_KEY_REMOVE as T, [...childFieldPathId.path, key]);
330327
},
331-
[onChange, childFieldPathId, formData],
328+
[onChange, childFieldPathId],
332329
);
333330

334331
if (!renderOptionalField || hasFormData) {
@@ -364,10 +361,7 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
364361
const hidden = getUiOptions<T, S, F>(fieldUiSchema).widget === 'hidden';
365362
const content = (
366363
<ObjectFieldProperty<T, S, F>
367-
// For regular properties, the key is just the name. For additionalProperties, the key is a combination of the
368-
// name and the hash of the formData so that react rerenders the components with the updated additional
369-
// property related callback which will change due to formData changes
370-
key={addedByAdditionalProperties ? `${name}-${formDataHash}` : name}
364+
key={name}
371365
propertyName={name}
372366
required={isRequired<S>(schema, name)}
373367
schema={get(schema, [PROPERTIES_KEY, name], {}) as S}

packages/utils/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* utility.
55
*/
66
export const ADDITIONAL_PROPERTY_FLAG = '__additional_property';
7+
export const ADDITIONAL_PROPERTY_KEY_REMOVE = Symbol('remove-this-key');
78
export const ADDITIONAL_PROPERTIES_KEY = 'additionalProperties';
89
export const ALL_OF_KEY = 'allOf';
910
export const ANY_OF_KEY = 'anyOf';

0 commit comments

Comments
 (0)