Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/FormController.js
Original file line number Diff line number Diff line change
Expand Up @@ -899,26 +899,26 @@ export class FormController {

if (!keepValue) {
debug('Delete Value', name);
ObjectMap.delete(this.state.values, name);
ObjectMap.unset(this.state.values, name);
debug('Delete Modified', name);
ObjectMap.delete(this.state.modified, name);
ObjectMap.unset(this.state.modified, name);
debug('Delete Masked', name);
ObjectMap.delete(this.state.maskedValues, name);
ObjectMap.unset(this.state.maskedValues, name);
}
if (!keepTouched) {
debug('Delete Touched', name);
ObjectMap.delete(this.state.touched, name);
ObjectMap.unset(this.state.touched, name);
}
if (!keepError) {
debug('Delete Errors', name);
ObjectMap.delete(this.state.errors, name);
ObjectMap.unset(this.state.errors, name);
}
debug('Delete Dirt', name);
ObjectMap.delete(this.state.dirt, name);
ObjectMap.unset(this.state.dirt, name);
debug('Delete Focused', name);
ObjectMap.delete(this.state.focused, name);
ObjectMap.unset(this.state.focused, name);
debug('Delete Info', name);
ObjectMap.delete(this.state.data, name);
ObjectMap.unset(this.state.data, name);

// Remember to update valid
this.updateValid();
Expand Down
12 changes: 12 additions & 0 deletions src/ObjectMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ export class ObjectMap {
}
}

// Like delete but never splices arrays -- just unsets the key.
// Used by FormController.remove() so that sibling field indices stay stable.
static unset(object, path) {
debug('UNSET', path);
ldunset(object, path);

let pathArray = ldtoPath(path);
pathArray = pathArray.slice(0, pathArray.length - 1);
cleanup(object, pathArray);
debug('UNSET DONE', path);
}

static delete(object, path) {
debug('DELETE', path);

Expand Down
33 changes: 22 additions & 11 deletions src/hooks/useField.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useFieldState } from './useFieldState';
import { useFormController } from './useFormController';
import { useCursorPosition } from './useCursorPosition';
import {
ArrayFieldItemStateContext,
MultistepStepContext,
RelevanceContext,
ScopeContext
Expand Down Expand Up @@ -154,6 +155,9 @@ export const useField = ({
// For multistep
const inMultistep = useContext(MultistepStepContext);

// For array field detection -- fields inside ArrayField have index-managed values
const inArrayField = useContext(ArrayFieldItemStateContext);

// For relevance
const isRelevant = useRelevance({
name,
Expand Down Expand Up @@ -351,17 +355,24 @@ export const useField = ({
[...formatterDependencies]
);

// Note im not adding this yet as I need to figure out how to solve issue with array fields when you remove 1 [0, 1, 2] and 2 becomes 1
// useUpdateEffect(
// () => {
// // If the form is pristine then reset it when we get new initial values !
// const pristine = fieldApi.getPristine();
// if (pristine) {
// fieldApi.reset();
// }
// },
// [userInitialValue, defaultValue]
// );
// Reset field when defaultValue/initialValue changes and form is still pristine.
// Previously disabled because remove() spliced arrays, shifting indices.
// Now safe because remove() uses ObjectMap.unset() which preserves indices.
// Skip for fields inside ArrayField -- their values are managed by the
// ArrayField's own index-shifting logic, not by defaultValue props.
useUpdateEffect(
() => {
if (inArrayField) {
return;
}

const pristine = fieldApi.getPristine();
if (pristine) {
fieldApi.reset();
}
},
[userInitialValue, defaultValue, inArrayField]
);

useFieldSubscription(
'field-value',
Expand Down