Javascript 使用带有挂钩的React.memo进行受控输入

Javascript 使用带有挂钩的React.memo进行受控输入,javascript,html,reactjs,react-hooks,Javascript,Html,Reactjs,React Hooks,我从一个定制的React钩子中提供了一些表单功能。这个钩子有一些类似于Formik的功能(但这是非常基本的东西) 表格如下: function Register() { const { handleSubmit, handleChange, handleBlur, values, errors, isSubmitting } = useFormValidation(INITIAL_STATE, validateAuth); // co

我从一个定制的React钩子中提供了一些表单功能。这个钩子有一些类似于Formik的功能(但这是非常基本的东西)

表格如下:

function Register() {
  const {
    handleSubmit,

    handleChange,
    handleBlur,
    values,
    errors,
    isSubmitting
  } = useFormValidation(INITIAL_STATE, validateAuth);
  // const [email, setEmail] = React.useState("");
  // const [password, setPassword] = React.useState("");

  return (
    <div className="container">
      <h1>Register Here</h1>
      <form onSubmit={handleSubmit}>
        <Input
          handleChange={handleChange}
          handleBlur={handleBlur}
          name="email"
          value={values.email}
          className={errors.email && "error-input"}
          autoComplete="off"
          placeholder="Your email address"
        />
        {errors.email && <p className="error-text">{errors.email}</p>}
        <Input
          handleChange={handleChange}
          handleBlur={handleBlur}
          value={values.password}
          className={errors.password && "error-input"}
          name="password"
          // type="password"
          placeholder="Choose a safe password"
        />
        {errors.password && <p className="error-text">{errors.password}</p>}
        <div>
          <button disabled={isSubmitting} type="submit">
            Submit
          </button>
        </div>
      </form>
    </div>
  );
}
函数寄存器(){
常数{
手推,
handleChange,
车把,
价值观
错误,
提交
}=useFormValidation(初始状态,validateAuth);
//const[email,setEmail]=React.useState(“”);
//const[password,setPassword]=React.useState(“”);
返回(
在这里注册
{errors.email&&

{errors.email}

} {errors.password&&

{errors.password}

} 提交 ); }
而记忆化的组件是下一个:

function Input({
  handleChange,
  handleBlur,
  name,
  value,
  className,
  autoComplete,
  placeholder,
  type
}) {

  return (
    <input
      onChange={handleChange}
      onBlur={handleBlur}
      name={name}
      value={value}
      className={className}
      autoComplete={autoComplete}
      placeholder={placeholder}
      type={type}
    />
  );
}

function areEqual(prevProps, nextProps) {
  console.log(`
    prevProps: ${JSON.stringify(prevProps.value)}
    nextProps: ${JSON.stringify(nextProps.value)}
  `);
  return prevProps.value === nextProps.value;
}
const useMemo = (component, propsAreEqual) => {
  return memo(component, propsAreEqual);
};
export default useMemo(Input, areEqual);
函数输入({
handleChange,
车把,
名称
价值
类名,
自动完成,
占位符,
类型
}) {
返回(
);
}
函数areEqual(prevProps,nextProps){
console.log(`
prevProps:${JSON.stringify(prevProps.value)}
nextProps:${JSON.stringify(nextProps.value)}
`);
返回prevProps.value==nextProps.value;
}
const UseMome=(组件、propsAreEqual)=>{
返回备忘录(组成部分、项目质量);
};
导出默认UseMoom(输入,areEqual);
我在第一次输入中输入了一些文本。然后,当我切换到第二个输入并开始键入时,第一个输入会丢失值。这就好像表单不是呈现最后一次的记忆输入,而是呈现以前的版本。
我是个新手,不能想出解决办法。有什么帮助吗?

尝试使用更新程序形式的
setState
,它具有以下功能:

function handleChange(event) {
  // event.target wont be available when fn is run in setState
  // so we save them in our own local variables here
  const { name, value } = event.target;

  setValues(prev => ({
    ...prev,
    [name]: value
  }));
}

您的
areEqual
方法转换为

仅当
值更改时重新呈现我的输入

但实际上,钩子的
handleChange
函数也在变化。另外,两个输入使用相同的
handleChange
。因此,
Input
只“记住”上次
值更改时的
handleChange
,由于
handleChange
通过闭包跟踪
值,因此它在创建
值时会“记住”值

更改
areEqual
方法(或完全忽略它)以验证
handleChange
中的更改将解决您的问题

function areEqual(prevProps, nextProps) {
  return (
    prevProps.value === nextProps.value &&
    prevProps.handleChange === nextProps.handleChange
  );
}

解决方案的代码沙盒

非常感谢您的回复!根据你的建议,我最后读了一些相关的东西。我在读这篇文章,但可能不是这样。(或者是吗?)@JoseMiguelOchoa
Input
显然有一个
handleChange
prop。你尝试过我的解决方案吗?谢谢你的回答。我现在明白你的意思了。我尝试过你的解决方案。我应该提到我使用了一个记忆输入,因为表单需要避免不必要的渲染。在我真正的项目表单中,我有很多选择和修改大量输入。它获取的表单没有响应(每个select都使用Apollo从Graphql端点获取数据)如果我不记下输入和选择。您当前的实现中可能会出现许多微妙的错误。如果
以外的任何道具发生更改,您的输入组件将不会重新渲染。现在可能会解决,但您永远不会知道。请记住这一点。谢谢您的建议!我会做得更一般一些,以便它可以接受m谢谢。
function areEqual(prevProps, nextProps) {
  return (
    prevProps.value === nextProps.value &&
    prevProps.handleChange === nextProps.handleChange
  );
}