Zain
Zain

Reputation: 61

How to Reset Dirty State for Nested Arrays and Objects Without Affecting Other Fields?

I am working on a multi-step form using React Hook Form, and I need to reset the dirty state of specific fields dynamically.

Form Structure:

Each question contains:

Each question is saved individually, and after saving, I want to reset its dirty state without affecting the rest of the form.


Example Form Data:


[
  {
    "options": [
      {
        "videos": [true],
        "text": true
      },
      {
        "videos": [true],
        "text": true
      }
    ],
    "text": true
  },
  {
    "options": [
      {
        "videos": [true],
        "text": true
      },
      {
        "videos": [true],
        "text": true
      }
    ],
    "text": true
  }
]

On my UI, each question has its own Save button. When saving, I want to clear the dirty fields for that specific question only.

Issue:

I created a recursive function using resetField() to reset only the dirty fields of the saved question.

✅ It works for primitive fields.
❌ But it does not reset the dirty state for arrays and objects.


Function Attempt:

const clearNestedDirtyFields = (dirtyObj, basePath = '') => {
  Object.keys(dirtyObj).forEach(key => {
    const path = basePath ? `${basePath}.${key}` : key;

    if (Array.isArray(dirtyObj[key])) {
      dirtyObj[key].forEach((item, index) => {
        const itemPath = `${path}[${index}]`;

        if (item === true) {
          resetField(itemPath, { keepDirty: false, defaultValue: watch(itemPath) });
        } else if (typeof item === 'object' && item !== null) {
          clearNestedDirtyFields(item, itemPath);
        }
      });
    } else if (dirtyObj[key] === true) {
      resetField(path, { keepDirty: false, defaultValue: watch(path) });
    } else if (typeof dirtyObj[key] === 'object' && dirtyObj[key] !== null) {
      clearNestedDirtyFields(dirtyObj[key], path);
    }
  });
};

What I Have Tried:

1️⃣ Adding logs to verify that the function correctly processes the nested fields ✅
2️⃣ Using resetField(path, { keepDirty: false }) explicitly
3️⃣ Using setValue(path, watch(path)) before resetting
4️⃣ resetField() works fine for primitive fields, but does not clear arrays or objects


Expected Behavior:

When I save a question, only that question’s fields (including nested options and videos) should have their dirty state reset, without affecting other questions or fields in the form.

Question:


Additional Utility Function (For Dirty Values Extraction)

I am using the following function to get dirty values:

export function getDirtyValues(dirtyFields, values) {
  return Object.keys(dirtyFields).reduce((prev, key) => {
    if (!dirtyFields[key] || values[key] === undefined) return prev;

    return {
      ...prev,
      [key]: typeof dirtyFields[key] === 'object' ? getDirtyValues(dirtyFields[key], values[key]) : values[key],
    };
  }, {});
}

Upvotes: 0

Views: 30

Answers (0)

Related Questions