React-hook-form не устанавливает для isDirty значение false, когда возвращается в исходное состояние

В официальном примере для контролируемых вводов, если вы измените значение ввода, а затем вернете его к исходному значению, isDirty будет установлено значение true, но не будет возвращено значение false, а dirtyField будет содержать затронутые поле.

В более старом примере с неконтролируемым вводом у нас другое поведение. На самом деле, если вы измените значение ввода, а затем вернете его к исходному значению, isDirty все равно будет ложным, но dirtyFields не будет содержать затронутое поле.

Разве isDirty не должно быть установлено обратно в false, когда форма возвращается в исходное состояние, а dirtyFields должно быть пустым?

Это предполагаемое поведение?

Контроллеры нарушают formState?

У нас та же проблема в нашем текущем проекте на работе.

O. Beaulieu 10.12.2020 19:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
12
1
27 906
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

isDirty основан на входных значениях формы по сравнению со значениями по умолчанию.

https://react-hook-form.com/api#formState

Обязательно укажите значения defaultValues ​​всех входных данных в форме useForm, поэтому перехватите форма может иметь единственный источник истины, чтобы сравнить, является ли форма грязный.

Вот пример с неконтролируемыми входами: https://codesandbox.io/s/bold-kapitsa-7m6o0?file=/src/App.tsx

пример с контролируемыми входами: https://codesandbox.io/s/dark-framework-op8jy?file=/src/App.tsx

С опозданием на два года, но добавляя к тому, что ответил Билл, и если у кого-то есть похожая проблема (как у меня). Мало того, что ему нужны значения по умолчанию в useForm, в объекте значений по умолчанию не может быть дополнительных свойств, которых нет в форме. Проблема, с которой я столкнулся, заключалась в том, что моя форма объединила значения по умолчанию (для новой записи) и объект данных (для редактирования существующей записи). Итак, если у вас было что-то вроде этого

const person = {id: 123, firstName: "Jane", lastName: "Smith"};

и ваша форма использовалась для редактирования и создания, компонент может иметь необязательную опору для «человека», а useForm настроен следующим образом.

const formMethod = useForm({
  defaultValues: person || {firstName: "", lastName: ""},
});

Я не добавлял «id» в форму, потому что ее никогда не собирались редактировать, и у вас нет id для создания, а значение было доступно для метода обновления. Может быть, это анти-шаблон, но это то, что было сделано.

При первом отображении формы isDirty будет иметь значение false. Когда вы меняете значение, isDirty становится истинным. Когда вы вернетесь к исходному значению, isDirty останется истинным, потому что ВСЕ значения по умолчанию не соответствуют входным значениям формы и никогда не будут соответствовать в этом случае.

Это упрощенный пример, когда идентификатор может быть добавлен в форму как скрытый ввод, зарегистрированный или что-то в этом роде, но для реального решения может быть много других полей, которые спускаются через API, которые не редактируются и не должны t (или не может) быть частью формы. Вывод таков: убедитесь, что ваша модель редактирования соответствует модели значений по умолчанию. Я использовал это для слияния объектов, удаления нулей, исправления отсутствующих реквизитов и удаления реквизитов, которых не было по умолчанию. «mergeWith» и «pick» — это методы lodash.

function mergeFormData(defaults: Object, data?: Object, removeExtras?: boolean) {
    if (!data) return defaults;

    // This should merge everything on data, and take
    // defaults where applicable.
    // It's only shallow merge, and it uses the "data" if it isn't null or undefined.
    // ?? should do it, so it will allow "" and 0 to be kept on the data object
    // Use removeExtras to take out props from the data object
    // that aren't on the default object

    return mergeWith({},
        removeExtras ? pick(data, Object.keys(defaults)) : data,
        defaults,
        (a, b) => {return a ?? b;});
}

И использование (в моем случае) для добавления/редактирования.

const formContext = useForm<AddressFormData>({
    defaultValues: mergeFormData(defaultAddress, address, true),
    resolver: yupResolver(addressSchema),
    mode: 'onBlur'
});

Хорошо сказано. В моем коде я не сбрасывал значение и хотел, чтобы isDirty было ложным после отправки данных формы. Позже я понял, что значение должно сбрасываться после отправки формы с любым значением по умолчанию или объектом, отправленным из API. Действительно застрял в этом более чем на 2 часа, надеясь помочь кому-нибудь с подобной ошибкой.

Prawesh Lamsal 07.03.2023 10:20

Обязательно подпишитесь на поле isDirty из useForm, тогда оно будет работать.

const { handleSubmit, control, formState: { isDirty }, } = useForm({ defaultValues: baseRecord, });

Другие вопросы по теме