Reactjs 触摸字段会导致钩形变脏

Reactjs 触摸字段会导致钩形变脏,reactjs,react-hook-form,Reactjs,React Hook Form,我对react钩子表单有一个问题,简单地“触摸”一个字段(点击它然后点击其他地方)就会导致formState.isDirty为真。我在这个代码沙盒中重现了这个问题: 我正在从服务器加载一条记录并调用reset(),以便将其视为新的基线,这可能是问题的原因。但是,作为一个动态表单,我需要从服务器检索要加载到表单中的对象,所以我看不出有什么办法可以解决这个问题。我只希望formState.isDirty保持为false,只要值没有实际更改 我自己只调用register('whatever')的更复

我对react钩子表单有一个问题,简单地“触摸”一个字段(点击它然后点击其他地方)就会导致formState.isDirty为真。我在这个代码沙盒中重现了这个问题:

我正在从服务器加载一条记录并调用reset(),以便将其视为新的基线,这可能是问题的原因。但是,作为一个动态表单,我需要从服务器检索要加载到表单中的对象,所以我看不出有什么办法可以解决这个问题。我只希望formState.isDirty保持为false,只要值没有实际更改

我自己只调用register('whatever')的更复杂的组件(如react select)没有这个问题,只有使用ref={register}的原生HTML输入才有这个问题

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>
  );
}
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
import React,{useState,useffect}来自“React”;
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
导入“/styles.css”; 从“react hook form”导入{useForm};
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
从“@hookform/resolvers/yup”导入{yupResolver}”;
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
从“yup”导入*作为yup; 导出默认函数App(){ 接口对象{ 测试:字符串; id:编号; }
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
常量blankObject:MyObject={ 测试:“默认值”, 身份证号码:0 };
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
const[obj,setObj]=使用状态(blankObject); const schema=yup.object().shape({ 测试:yup.string().max(40) });
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
常量{register,handleSubmit,formState,reset,errors}=useForm<
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
肌体 >({ 解析程序:yupResolver(模式), 默认值:blankObject });
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
useffect(()=>{ 设置超时(()=>{ 常数newObj={ 测试:“假装这来自服务器”, 身份证号码:123 };
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
setObj(newObj); 重置(newObj); }, 2000);
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
},[reset]);
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
const onSubmit=(数据:MyObject)=>{ 警报(JSON.stringify(数据)); };
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
常量onReset=()=>{ 重置(); };
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
返回( {obj.id==0( 请稍候

) : ( ID:{obj.ID}

const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
输入文本: {errors.testing&&( {错误.测试?.message}
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
)}
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
{JSON.stringify(formState,null,2)}
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
)}
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
); }
const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};
我可能可以去掉ref={register}并手动处理注册,但这样做似乎有点偏离了react hook表单的要点

const newObj = {
  testing: "Pretend this came from the server",
  id: 123
};

谢谢。

React hook表单如何验证表单是否脏取决于深度比较
默认值

以下是示例的
默认值
:(重置后)

但是,在钩子表单中没有注册的
id
字段。因此,比较也将是不匹配的,因为缺少
id

下面的示例可能会为您提供更好的上下文


如果我修改我的示例,将“defaultValues:blankObject”添加到useForm构造函数中,它仍然会通过聚焦和取消聚焦字段而导致表单变脏。@问题在于
id
输入在哪里?我明白你的意思。德拉茨。我希望使用一个现有的对象接口(对于这个特殊的表单,它还有其他我想忽略的字段)。因此,我必须专门将我感兴趣的那些属性设置为默认值,并且无论何时调用reset?:-(我想你可以试着在useForm上设置shouldUnregister:false,它可能对你有效,那么id将是一个虚拟输入。是的。谢谢你的帮助。