В официальном примере для контролируемых вводов, если вы измените значение ввода, а затем вернете его к исходному значению, isDirty
будет установлено значение true, но не будет возвращено значение false, а dirtyField
будет содержать затронутые поле.
В более старом примере с неконтролируемым вводом у нас другое поведение. На самом деле, если вы измените значение ввода, а затем вернете его к исходному значению, isDirty
все равно будет ложным, но dirtyFields
не будет содержать затронутое поле.
Разве isDirty
не должно быть установлено обратно в false, когда форма возвращается в исходное состояние, а dirtyFields
должно быть пустым?
Это предполагаемое поведение?
Контроллеры нарушают formState?
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 часа, надеясь помочь кому-нибудь с подобной ошибкой.
Обязательно подпишитесь на поле isDirty из useForm, тогда оно будет работать.
const { handleSubmit, control, formState: { isDirty }, } = useForm({ defaultValues: baseRecord, });
У нас та же проблема в нашем текущем проекте на работе.