触摸字段会导致 react-hook-form 变脏
Touching fields causes react-hook-form to become dirty
我对 react-hook-form 有一个问题,即简单地“触摸”一个字段(点击它然后点击其他地方)导致 formState.isDirty 为真。我已经在这个 codesandbox 中重现了这个问题:
https://codesandbox.io/s/react-hook-form-dirty-by-touch-p8x6j
我正在从服务器加载一条记录并调用 reset() 以便它被视为新的基线,这可能是问题的原因。但是,作为一个动态表单,我需要从服务器检索对象以加载到表单中,所以我看不出解决这个问题的办法。我只想让 formState.isDirty 保持假,只要值没有实际改变。
对于更复杂的组件(例如 react-select)我没有这个问题,我只是自己调用 register('whatever'),它只是原生 HTML 我使用 ref={register} 的输入有这个问题。
import React, { useState, useEffect } from "react";
import "./styles.css";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
interface MyObject {
testing: string;
id: number;
}
const blankObject: MyObject = {
testing: "Default value",
id: 0
};
const [obj, setObj] = useState(blankObject);
const schema = yup.object().shape({
testing: yup.string().max(40)
});
const { register, handleSubmit, formState, reset, errors } = useForm<
MyObject
>({
resolver: yupResolver(schema),
defaultValues: blankObject
});
useEffect(() => {
setTimeout(() => {
const newObj = {
testing: "Pretend this came from the server",
id: 123
};
setObj(newObj);
reset(newObj);
}, 2000);
}, [reset]);
const onSubmit = (data: MyObject) => {
alert(JSON.stringify(data));
};
const onReset = () => {
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{obj.id === 0 ? (
<p>Please wait...</p>
) : (
<div>
<p>ID: {obj.id}</p>
<label>Enter text: </label>
<input
type="text"
name="testing"
ref={register}
autoComplete="off"
style={{ width: "50%" }}
defaultValue={obj.testing}
/>
{errors.testing && (
<div style={{ color: "#ff0000" }}>{errors.testing?.message}</div>
)}
<pre>{JSON.stringify(formState, null, 2)}</pre>
<input type="submit" />
<input type="button" value="reset" onClick={onReset} />
</div>
)}
</form>
);
}
我可能可以摆脱 ref={register} 并手动处理注册,但这样做似乎有点偏离了 react-hook-form 的要点。
谢谢。
React hook 表单如何验证表单是否脏是基于深度比较defaultValues
。
这是您的示例 defaultValues
:(重置后)
const newObj = {
testing: "Pretend this came from the server",
id: 123
};
然而,没有id
got registered at hook form这样的字段。所以比较也将是不匹配的,因为缺少 id
。
以下示例可能会给您更好的上下文。
我对 react-hook-form 有一个问题,即简单地“触摸”一个字段(点击它然后点击其他地方)导致 formState.isDirty 为真。我已经在这个 codesandbox 中重现了这个问题:
https://codesandbox.io/s/react-hook-form-dirty-by-touch-p8x6j
我正在从服务器加载一条记录并调用 reset() 以便它被视为新的基线,这可能是问题的原因。但是,作为一个动态表单,我需要从服务器检索对象以加载到表单中,所以我看不出解决这个问题的办法。我只想让 formState.isDirty 保持假,只要值没有实际改变。
对于更复杂的组件(例如 react-select)我没有这个问题,我只是自己调用 register('whatever'),它只是原生 HTML 我使用 ref={register} 的输入有这个问题。
import React, { useState, useEffect } from "react";
import "./styles.css";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
interface MyObject {
testing: string;
id: number;
}
const blankObject: MyObject = {
testing: "Default value",
id: 0
};
const [obj, setObj] = useState(blankObject);
const schema = yup.object().shape({
testing: yup.string().max(40)
});
const { register, handleSubmit, formState, reset, errors } = useForm<
MyObject
>({
resolver: yupResolver(schema),
defaultValues: blankObject
});
useEffect(() => {
setTimeout(() => {
const newObj = {
testing: "Pretend this came from the server",
id: 123
};
setObj(newObj);
reset(newObj);
}, 2000);
}, [reset]);
const onSubmit = (data: MyObject) => {
alert(JSON.stringify(data));
};
const onReset = () => {
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{obj.id === 0 ? (
<p>Please wait...</p>
) : (
<div>
<p>ID: {obj.id}</p>
<label>Enter text: </label>
<input
type="text"
name="testing"
ref={register}
autoComplete="off"
style={{ width: "50%" }}
defaultValue={obj.testing}
/>
{errors.testing && (
<div style={{ color: "#ff0000" }}>{errors.testing?.message}</div>
)}
<pre>{JSON.stringify(formState, null, 2)}</pre>
<input type="submit" />
<input type="button" value="reset" onClick={onReset} />
</div>
)}
</form>
);
}
我可能可以摆脱 ref={register} 并手动处理注册,但这样做似乎有点偏离了 react-hook-form 的要点。
谢谢。
React hook 表单如何验证表单是否脏是基于深度比较defaultValues
。
这是您的示例 defaultValues
:(重置后)
const newObj = {
testing: "Pretend this came from the server",
id: 123
};
然而,没有id
got registered at hook form这样的字段。所以比较也将是不匹配的,因为缺少 id
。
以下示例可能会给您更好的上下文。