【问题标题】:Error with creating React form with function components使用功能组件创建 React 表单时出错
【发布时间】:2021-01-25 19:50:25
【问题描述】:

今天我只是想用功能组件和使用 React 的 useState 钩子创建一个用于登录/注册的表单。但是,我遇到了这个问题。如果有人可以提供帮助,将不胜感激。我试图寻找一个原因,然而,它无济于事。谢谢。

  • 只要我在电子邮件字段中提供输入,我就会收到警告。 ''警告:组件正在将未定义类型的受控输入更改为不受控。输入元素不应从受控切换到不受控(反之亦然)。 '' 我不知道我的代码哪里出了问题。
function Login(){
   const [state, setState] = useState({
       email:'',
       password:'',
   })

   const handleChange = e => {
       setState({ [e.target.name]: e.target.value })
   } 

   const handleSubmit = e => {
       e.preventDefault();
       var email = state.email;
       var password = state.password;

       // Firebase requires passwords to be of length 6 or above
       if (password.length < 6) {
           alert("Password must of length 6 or more.");
       } else {
           fire.auth().createUserWithEmailAndPassword(email, password); 
           
           alert("Signed Up Successfully!");
       }
   }

   return(
       <>
       <Navbar/>
       <div>
           <form>
               <input name="email" value={state.email} onChange={handleChange} placeholder="email"></input>
               <input name="password" value={state.password} onChange={handleChange} placeholder="password"></input>
               <button type="submit" onClick={handleSubmit}>Sign Up!</button>
               <button type="submit">Login!</button>
           </form>
       </div>
       </>
   );
}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    useState 中钩住旧状态,并且您传递给setState 函数的对象不会像类组件的setState 那样自动合并。这里需要确保当你调用setState所有状态属性连同状态的更新属性都存在。

    否则你传递给setState的对象将替换当前状态的对象。

    你的状态有两个属性:

    {
       email:'',
       password:'',
    } 
    

    但是当您更新handleChange 中的状态时,您会省略一个状态属性。与缺失属性关联的输入从受控组件变为不受控组件,因此您会收到错误:

    const handleChange = e => {
       setState({ [e.target.name]: e.target.value })
    } 
    

    您需要将旧状态与更新后的属性合并:

    const handleChange = e => {
       setState({ ...state, [e.target.name]: e.target.value })
    } 
    

    或者将状态拆分为两个 useState 调用,每个属性调用一个:

    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    

    然后为每个更新处理程序:

    const handleEmailChange = e => {
      setEmail({ [e.target.name]: e.target.value })
    }
    
    const handlePasswordChange = e => {
      setPassword({ [e.target.name]: e.target.value })
    }
    

    【讨论】:

    • 谢谢,这是有道理的。但是,您可以详细说明 ...state 的实际作用。我还在学习 React 所以如果你不介意!!
    • 我喜欢将电子邮件和密码分开,但我想最好的做法应该是使用 ...state 代替,如果我没记错的话!
    • @TanDev,您可能认为您从useState 调用中获得的setState 的行为类似于类组件的setState,事实并非如此。您从钩子传递给 setState 的对象完全替换了旧状态,因此在您的情况下,更新的一个属性保持在该状态中,而另一个属性在您更新状态时被删除。因此,与缺失属性相关的输入变得不受控制
    • 是的,我现在明白了。感谢您的明确解释。但我仍然想知道,setState 中的 '...state' 是否只负责合并状态?如果是这样,那到底是怎么发生的。
    • @TanDev 是对象扩展运算符。基本上... 在对象将对象传播到各个属性之前,然后您提供更新的属性,因此新生成的对象具有所有以前的属性以及新的更新属性
    【解决方案2】:

    useState 更新整个对象,而不是特定的值,与类组件中的 setState 不同。 所以你需要析构state的现有值并添加更新的值,请在下面找到更新的句柄更改代码:

    function Login(){
       const [state, setState] = useState({
           email:'',
           password:'',
       })
    
       const handleChange = e => {
           setState({ 
                     ...state,
                    [e.target.name]: e.target.value })
    
       } 
    
       const handleSubmit = e => {
           e.preventDefault();
           var email = state.email;
           var password = state.password;
    
           // Firebase requires passwords to be of length 6 or above
           if (password.length < 6) {
               alert("Password must of length 6 or more.");
           } else {
               fire.auth().createUserWithEmailAndPassword(email, password); 
               
               alert("Signed Up Successfully!");
           }
       }
    
       return(
           <>
           <Navbar/>
           <div>
               <form>
                   <input name="email" value={state.email} onChange={handleChange} placeholder="email"></input>
                   <input name="password" value={state.password} onChange={handleChange} placeholder="password"></input>
                   <button type="submit" onClick={handleSubmit}>Sign Up!</button>
                   <button type="submit">Login!</button>
               </form>
           </div>
           </>
       );
    }
    

    【讨论】:

    • 谢谢,这是有道理的。但是,您可以详细说明 ...state 的实际作用。我还在学习 React 所以如果你不介意!!
    猜你喜欢
    • 1970-01-01
    • 2014-11-20
    • 2021-12-07
    • 2019-09-15
    • 1970-01-01
    • 2021-08-18
    • 2020-05-30
    • 2017-07-05
    • 1970-01-01
    相关资源
    最近更新 更多