next.js useRef的数据在由useImperativeHandle调出时延迟

rur96b6h  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(87)

我正在使用输入组件中的useImperativeHandle将ref的数据传递到登录组件,但当emailInputRef的数据与inputRef的数据相比延迟时,我遇到了问题

const Login = () => {
  const router = useRouter();
  const [isvalid, setIsValid] = useState(true);

  const emailInputRef = useRef();
  const passwordInputRef = useRef();

  const email = emailInputRef.current?.value;
  const password = passwordInputRef.current?.value;

  console.log("data in login: ", email, password);

  const submitHandler = async (event) => {
    event.preventDefault();

    setIsValid((prevState) => !prevState);

    // return router.push("/dashboard");
  };

  return (
    <div className={styles.login}>
      <div className={styles.card}>
        <p className={styles["signin-label"]}>Log In</p>
        <form onSubmit={submitHandler} className={styles["signin-form"]}>
          <Input
            ref={emailInputRef}
            name="email"
            type="email"
            placeholder="Email"
          />
          <p className={styles["none-display"]}>Please enter a valid email.</p>
          <Input
            ref={passwordInputRef}
            name="password"
            type="password"
            placeholder="Password"
          />
          <p className={isvalid ? styles["none-display"] : ""}>
            Incorrect Email or Password.
          </p>
          <Button>Log In</Button>
        </form>
        <div className={styles["sign-up"]}>
          <p>Need an account?</p>
          <Link href="/signup">Sign up now.</Link>
        </div>
      </div>
    </div>
  );
};

个字符
here is the data output
我不知道是什么问题。我不想使用useState,因为我不想我的组件在输入改变时重新呈现。请帮助。

pkln4tw6

pkln4tw61#

您的emailpassword值在submitHandler中是未定义的,这是因为您的Login组件从初始渲染开始就不会重新渲染,直到您使用setIsValid更改其状态。
在每个XML上重新呈现Login组件并没有什么真正的问题,而且您不会看到任何明显的性能损失,除非您正在处理非常大的表单。
此外,在命令式处理程序的实现中,您捕获的是useImperativeHandle运行时的输入值,它不会反映当前值。
以下是我可以为您推荐的两种实施方案:

1)控制输入

在本例中,Login组件会在每一个XML上重新呈现,但额外的好处是您可以在用户输入时执行验证。

import * as React from "react";
import Input from "./Input";

export default function Login() {
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [isValid, setIsValid] = React.useState(true);

  const clear = () => {
    setEmail("");
    setPassword("");
  };

  const onSubmit = (event) => {
    event.preventDefault();

    console.log({ email, password });

    setIsValid((prev) => !prev);
  };

  return (
    <form noValidate onSubmit={onSubmit}>
      <p>Log In</p>

      <Input
        name="email"
        type="email"
        label="Email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
      />

      <Input
        name="password"
        type="password"
        label="Password"
        value={password}
        onChange={(event) => setPassword(event.target.value)}
      />

      {!isValid && <p>Incorrect Email or Password.</p>}

      <button type="submit">Log In</button>

      <button type="button" onClick={clear}>Clear</button>
    </form>
  );
}

个字符

2)不受控输入

在这种情况下,Login组件不会在每个表单上重新呈现,并且您只能在提交表单时验证用户输入。

import * as React from "react";
import Input from "./Input";

export default function Login() {
  const emailRef = React.useRef(null);
  const passwordRef = React.useRef(null);
  const [isValid, setIsValid] = React.useState(true);

  const clear = () => {
    emailRef.current.value = "";
    passwordRef.current.value = "";
  };

  const onSubmit = async (event) => {
    event.preventDefault();

    const formData = new FormData(event.target);
    const email = formData.get("email");
    const password = formData.get("password");

    console.log({ email, password });

    // or alternatively
    // console.log({
    //   email: emailRef.current.value,
    //   password: passwordRef.current.value,
    // });

    setIsValid((prev) => !prev);
  };

  return (
    <form noValidate onSubmit={onSubmit}>
      <p>Log In</p>

      <Input ref={emailRef} name="email" type="email" label="Email" />

      <Input
        ref={passwordRef}
        name="password"
        type="password"
        label="Password"
      />

      {!isValid && <p>Incorrect Email or Password.</p>}

      <button type="submit">Log In</button>

      <button type="button" onClick={clear}>
        Clear
      </button>
    </form>
  );
}
import * as React from "react";

export default React.forwardRef(function Input(
  { type, name, label, required },
  ref,
) {
  return (
    <div>
      <label>{label}</label>
      <input ref={ref} name={name} type={type} required={required} />
    </div>
  );
});

的字符串
但是,如果您确实需要使用useImperativeHandle,因为您最初的问题中没有列出的其他原因,您可以按照以下方式实现沿着:

useImperativeHandle(
  ref,
  () => ({
    getValue: () => inputRef.current.value,
    clear: () => (inputRef.current.value = ""),
  }),
  []
);

相关问题