【问题标题】:Onchange in React input causes the input to rerender on every letterReact 输入中的 Onchange 导致输入在每个字母上重新呈现
【发布时间】:2021-12-03 22:21:48
【问题描述】:

所以我在两个函数中创建了输入,并在Onchange 上获取了输入到它们中的值。但是每当我输入输入时,我一次只能输入一个字母,然后才会失去焦点,我相信这是因为组件一直在渲染。 我还意识到,每当我删除 Onchange 和 value 道具时,一切都会恢复正常,我可以轻松地输入所有内容。我该如何解决这个问题?

App.js

import style from "./auth.module.css";
import { useEffect, useRef, useState } from "react";
import { useAuthState } from 'react-firebase-hooks/auth';
import { auth, signInWithEmailAndPassword, signInWithGoogle, registerWithEmailAndPassword } from "../../firebase";
import { CSSTransition } from "react-transition-group";


function Auth() {
  const [activeMenu, setActiveMenu] = useState("main");
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [user, loading, error] = useAuthState(auth);

  const Emailform = () => {
    return (
      <div className={style.formBox}>
        <label className={style.label}>Email:</label>
        <form className={style.input}>
          <input 
            type="email" 
            name="email" 
            required="true"
            value={email} 
            onChange={(e) => setEmail(e.target.value)} />
        </form>
      </div>
    );
  }
  
  const Passform = () => {
    return (
      <div className={style.formBox}>
        <label className={style.label}>Password:</label>
  
        <form className={style.input}>
          <input 
            type="password" 
            name="password" 
            required="true"
            value={password} 
            onChange={(e) => setPassword(e.target.value)} />
        </form>
      </div>
    );
  }

  let domNode = useClickOutside(() => {
    setActiveMenu(false);
  });

  return (
    <div className={style.container}>
      <Login />
      <Signup />
    </div>
  );

  function AuthType(props) {
    return (
      <a
        href={props.link}
        className={style.menuItem}
        onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}
      >
        {props.children}
      </a>
    );
  }


/* Login */
  function Login() {
    return (
      <CSSTransition in={activeMenu === "main"} unmountOnExit timeout={500}>
        <div ref={domNode}>
          <div className={style.login}>
            <h1 className={style.title}>Clip It</h1>
            {/* Email and Password */}
            <Emailform/>
            <Passform/>

            <div className={style.button}>
              <input 
                type="submit" 
                value="Login"
                onClick={() => signInWithEmailAndPassword(email, password)} />
              <input 
                type="submit" 
                value="Login with Google"
                onClick={signInWithGoogle} />
            </div>
            <div className={style.text}>
              <p className={style.plink}>Forgot Password</p>
              <div>
                Need an account?&nbsp;
                <AuthType goToMenu="Signup">click here</AuthType>
              </div>
            </div>
          </div>
        </div>
      </CSSTransition>
    );
  }


  function Signup() {
    return (
      <CSSTransition in={activeMenu === "Signup"} unmountOnExit timeout={500}>
        <div ref={domNode}>
          <div className={style.signUp}>
            <div className={style.title}> Clip It</div>
            <Form label="First Name" type="text" />
            <Form label="Last Name" type="Text" />
            <Form label="Email" type="email"/>
            <Form label="Date of Birth" type="date" />
            <Form label="Password" type="password"/>
            <Form label="Confirm Password" type="password" />
            <div className={style.button}>
              <input type="submit" value="Sign Up" />
            </div>
            <div className={style.text}>
              have an&nbsp;
              <AuthType goToMenu="main"> account</AuthType>
            </div>
          </div>
        </div>
      </CSSTransition>
    );
  }
}
let useClickOutside = (handler) => {
  let domNode = useRef();

  useEffect(() => {
    let clickListener = (event) => {
      if (domNode.current && !domNode.current.contains(event.target)) {
        handler();
      }
    };

    document.addEventListener("mousedown", clickListener);

    return () => {
      document.removeEventListener("mousedown", clickListener);
    };
  });
  return domNode;
};

function Form(props) {
  return (
    <div className={style.formBox}>
      <label className={style.label}>{props.label}:</label>

      <form className={style.input}>
        <input 
          type={props.input} 
          name={props.input} 
          required="true" />
      </form>
    </div>
  );
}

export default Auth;

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    可能重复:In React ES6, why does the input field lose focus after typing a character?

    一种解决方案是将电子邮件表单移到父组件之外。

    const Emailform = ({ onChange }) => {
      return (
        <div>
          <label>Email:</label>
          <form>
            <input
              type="email"
              name="email"
              required="true"
              onChange={onChange}
            />
          </form>
        </div>
      );
    };
    
    const App = () => {
      const [email, setEmail] = useState("");
      return (
        <div>
            <Emailform onChange={(e) => setEmail(e.target.value)} />
        </div>
      );
    };
    

    【讨论】:

    • 仍然没有变化...而且更糟糕的是,我现在无法输入任何内容...
    • 在不将电子邮件/值传递给 Emailform 的情况下试一试。我已将其从示例中删除。
    • 这也不行……
    【解决方案2】:

    不要将您的组件定义放在其他组件中。如果这样做,您会在每次渲染时创建一个新组件。

    您需要设法将 Emailform、Passform 移到 Auth 之外。

    结帐this sandbox 进行实验

    function Auth() {
      // ? the bad place to define components
      const Emailform = () => {
        ...
      }
      // ? the bad place to define components
      const Passform = () => {
        ...
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-11
      • 2021-03-16
      • 2021-03-16
      • 1970-01-01
      • 2021-05-19
      • 2018-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多