回到初始状态时,React-hook-form 不会将 isDirty 设置为 false
React-hook-form doesn't set isDirty to false when back to initial state
在官方的exemple for controlled inputs中,如果你修改了一个input的值,然后再改回初始值,isDirty
会被设置为true,但不会被设置回false 和 dirtyField
将包含触摸字段。
在较旧的 exemple with uncontrolled inputs 中,我们的行为并不完全相同。事实上,如果你修改一个输入的值,然后将它改回它的初始值,isDirty
仍然是假的,但 dirtyFields
将不包含被触摸的字段。
当表单返回初始状态并且 dirtyFields
应该为空时,不应该将 isDirty
设置回 false 吗?
这是预期的行为吗?
Controller 是否破坏了 formState?
isDirty
基于表单输入值与默认值的对比。
https://react-hook-form.com/api#formState
Make sure to provide all inputs' defaultValues at the useForm, so hook
form can have a single source of truth to compare whether the form is
dirty.
这是一个不受控制的输入的例子:
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"};
并且您的表单用于编辑和创建,该组件可以有一个可选的“person”属性,并且 useForm 设置如下
const formMethod = useForm({
defaultValues: person || {firstName: "", lastName: ""},
});
我没有在表单中添加“id”,因为它永远不会被编辑,而且您没有用于创建的 id,并且该值可用于更新方法。也许那是一个 anti-pattern,但它已经完成了。
首次呈现表单时,isDirty 将为 false。当您更改值时,isDirty 将为真。当您更改回原始值时,isDirty 保持为真,因为所有默认值都不匹配表单输入值,并且在这种情况下永远不会匹配。
这是一个简单的示例,其中可以将 id 作为隐藏输入或注册之类的形式添加到表单中,但对于真正的解决方案,可能还有许多其他字段正在 api 不可编辑且不应(或不能)成为表单的一部分。要点是——确保您的编辑模型与您的默认值模型相匹配。我用它来合并对象、删除空值、修补缺失的道具并删除默认情况下不存在的道具。 “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;});
}
以及 add/edit.
的用法(在我的例子中)
const formContext = useForm<AddressFormData>({
defaultValues: mergeFormData(defaultAddress, address, true),
resolver: yupResolver(addressSchema),
mode: 'onBlur'
});
在官方的exemple for controlled inputs中,如果你修改了一个input的值,然后再改回初始值,isDirty
会被设置为true,但不会被设置回false 和 dirtyField
将包含触摸字段。
在较旧的 exemple with uncontrolled inputs 中,我们的行为并不完全相同。事实上,如果你修改一个输入的值,然后将它改回它的初始值,isDirty
仍然是假的,但 dirtyFields
将不包含被触摸的字段。
当表单返回初始状态并且 dirtyFields
应该为空时,不应该将 isDirty
设置回 false 吗?
这是预期的行为吗?
Controller 是否破坏了 formState?
isDirty
基于表单输入值与默认值的对比。
https://react-hook-form.com/api#formState
Make sure to provide all inputs' defaultValues at the useForm, so hook form can have a single source of truth to compare whether the form is dirty.
这是一个不受控制的输入的例子: 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"};
并且您的表单用于编辑和创建,该组件可以有一个可选的“person”属性,并且 useForm 设置如下
const formMethod = useForm({
defaultValues: person || {firstName: "", lastName: ""},
});
我没有在表单中添加“id”,因为它永远不会被编辑,而且您没有用于创建的 id,并且该值可用于更新方法。也许那是一个 anti-pattern,但它已经完成了。
首次呈现表单时,isDirty 将为 false。当您更改值时,isDirty 将为真。当您更改回原始值时,isDirty 保持为真,因为所有默认值都不匹配表单输入值,并且在这种情况下永远不会匹配。
这是一个简单的示例,其中可以将 id 作为隐藏输入或注册之类的形式添加到表单中,但对于真正的解决方案,可能还有许多其他字段正在 api 不可编辑且不应(或不能)成为表单的一部分。要点是——确保您的编辑模型与您的默认值模型相匹配。我用它来合并对象、删除空值、修补缺失的道具并删除默认情况下不存在的道具。 “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;});
}
以及 add/edit.
的用法(在我的例子中)const formContext = useForm<AddressFormData>({
defaultValues: mergeFormData(defaultAddress, address, true),
resolver: yupResolver(addressSchema),
mode: 'onBlur'
});