Javascript 在提交表单时执行表单验证时,组件未在React中更新

Javascript 在提交表单时执行表单验证时,组件未在React中更新,javascript,reactjs,redux,react-hooks,Javascript,Reactjs,Redux,React Hooks,我登录了react import React, { Fragment, useState } from 'react'; import { useHistory } from "react-router-dom"; import { useDispatch } from 'react-redux'; import { Link } from 'react-router-dom'; import { auth } from '../actions'; export const Login =

我登录了react

import React, { Fragment, useState } from 'react';
import { useHistory } from "react-router-dom";
import { useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';

import { auth } from '../actions';


export const Login = () => {
   let history = useHistory();
   const dispatch = useDispatch();

   const [email, setEmail] = useState('');
   const [password, setPassword] = useState('');
   const [error, setError] = useState({email: '', password: ''});

   const validEmailRegex = RegExp(/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|. 
    (\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i);

   const handleChange = e => {
      e.persist();
      const { name, value } = e.target;
      let validationError = error;

      switch(name) {
        case 'email':
            setEmail(value);
            validationError.email = validEmailRegex.test(value) ? '' : 'Email is not valid';
            break;
        case 'password':
            setPassword(value)
            validationError.password = value.length < 8 ? 'Password must be 8 characters 
            long!': '';
            break;
        case 'submit':
            validationError.email = email.length < 1 ? 'Email is required'  : '';
            validationError.password = password.length < 1 ? 'Password is required'  : '';
        default:
            break;
      };
    setError(validationError);
    console.log('in change', error)
   };

const validateForm = (errors) => {
    let valid = true;
    Object.values(errors).forEach(
      // if we have an error string set valid to false
      (val) => val.length > 0 && (valid = false)
    );
    return valid;
};

const validate = () => {
    console.log('email,password', email, password);
    let validationError = error;
    if(!email){
        validationError.email = 'Email is required';
    }
    if(!password){
        validationError.password = 'Password is required';
    }
    setError(validationError);
    console.log('in validate',error)
};

const onSubmit = e => {
    e.preventDefault();
    validate();
    console.log('error on submit', error);
    if(validateForm(error)) {
        dispatch(auth(email, password, true));
        history.replace('/home');
      }else{
        console.error('Invalid Form', error)
      }
};
return (
    <Fragment>
        <div className="w-full max-w-sm container mt-20 mx-auto">
            <form onSubmit={onSubmit}>
                <div className="w-full mb-5">
                    <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" htmlFor="email">
                        Email
                    </label>
                    <input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:text-gray-600" value={email} name='email' onChange={(e) => handleChange(e)} type="text" placeholder="Email" />
                    { error && <span style={{color: "red"}}>{error['email']}</span>}
                </div>
                <div className="w-full  mb-5">
                    <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" htmlFor="password">
                        Password
                    </label>
                    <input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:text-gray-600" value={password} name='password' onChange={(e) => handleChange(e)} type="password" placeholder="Password" />
                    { error && <span style={{color: "red"}}>{error['password']}</span>}
                </div>
                <div className="flex items-center justify-between">
                    <button className="mt-5 bg-green-400 w-full hover:bg-green-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
                        Login
                    </button>
                </div>
                <div className="text-center mt-4 text-gray-500"><Link to='/'>Cancel</Link></div>
            </form>
        </div>
    </Fragment>
)
import React,{Fragment,useState}来自'React';
从“react router dom”导入{useHistory};
从'react redux'导入{useDispatch};
从'react router dom'导入{Link};
从“../actions”导入{auth};
导出常量登录=()=>{
让历史=使用历史();
const dispatch=usedpatch();
const[email,setEmail]=useState(“”);
const[password,setPassword]=useState(“”);
const[error,setError]=useState({电子邮件:'',密码:'});
常量validEmailRegex=RegExp(/^([^()\[\]\,;:\s@\“]+(\.[^()\[\]\,;:\s@\“]+)*)|。
(\“+\”)@(([^()[\]\,;:\s@\“]+\)+[^()[\]\,;:\s@\“]{2,})美元/i);
常量handleChange=e=>{
e、 坚持();
常量{name,value}=e.target;
让validationError=错误;
交换机(名称){
“电子邮件”案例:
设置电子邮件(值);
validationError.email=validEmailRegex.test(值)?“”:“电子邮件无效”;
打破
案例“密码”:
设置密码(值)
validationError.password=value.length<8?密码必须为8个字符
长!“:”;
打破
“提交”案例:
validationError.email=email.length<1?“需要电子邮件”:“;
validationError.password=password.length<1?“需要密码”:“”;
违约:
打破
};
设置错误(validationError);
console.log('in change',error)
};
常量validateForm=(错误)=>{
让valid=true;
Object.values(errors.forEach)(
//如果我们有一个错误字符串设置为false
(val)=>val.length>0&&(valid=false)
);
返回有效;
};
常量验证=()=>{
console.log('email,password',email,password);
让validationError=错误;
如果(!电子邮件){
validationError.email='需要电子邮件';
}
如果(!密码){
validationError.password='需要密码';
}
设置错误(validationError);
console.log('in validate',error)
};
const onSubmit=e=>{
e、 预防默认值();
验证();
console.log('提交时出错',错误);
if(validateForm(错误)){
发送(验证(电子邮件、密码、真));
历史记录。替换('/home');
}否则{
console.error('Invalid Form',error)
}
};
返回(
电子邮件
handleChange(e)}type=“text”placeholder=“Email”/
{error&&{error['email']}
密码
handleChange(e)}type=“password”placeholder=“password”/
{error&&{error['password']}
登录
取消
)
}

我在onchange和submit中添加了字段验证,onchange验证工作正常,并显示错误。提交时的验证也很好,但当我尝试提交时,组件仍然没有显示错误,字段没有任何更改

我是个新手,不知道这样做是否正确。提前谢谢。

我把你的代码放在一个文件夹中,它似乎工作得很好。请注意,我删除了
className
属性和注释了测试问题时不需要的内容,如
redux
导入

由于我删除了
className
属性,这可能是一个
CSS
问题,您的错误
span
实际呈现但不可见(查看浏览器的开发工具,看看
span
是否真的不存在)

另外,如果您使用大量表单,我建议您使用库,因为状态处理+验证可能会变得非常复杂,而且有很多解决方案。
我写了我自己的图书馆--随便看看

编辑

这里的问题是,当您使用
setError
更新
error
对象时,始终传递相同的对象引用:

//这不是在复制
//validationError将具有与error相同的引用
让validationError=错误;
// ...
//以下行不会触发重新加载
设置错误(validationError);
由于
error
validationError
具有相同的引用,
react
将检测到未发生任何更改,因此将导致。如果使用状态为的复杂类型(如对象或数组),则始终需要创建新引用,而不是调整前一个引用:

//这是使用扩展运算符的实际副本
//validationError将具有与error不同的引用
让validationError={…error};
// ...
//按预期触发重新加载
设置错误(validationError);
编辑2

我为
validate
添加了一个返回值,以便在调用
validateForm
时使用更新的
validationError
对象

const validate=()=>{
//..
让validationError={…error};
// ...
返回验证错误;
};
const onSubmit=e=>{
// ...
const validationError=validate();
if(validateForm(validationError)){
//...
}
};

请参阅。

按照此操作,当我尝试在不更改字段的情况下提交时,它可能会帮助您从它不起作用开始。@LakshmipriyaMukundan抱歉,我完全忽略了这一部分。。我更新了答案现在问题是错误变量没有更新,“validationError”的值正确。但我认为setError不能正常工作。@LakshmipriyaMukundan我添加了一个新的代码沙盒,其中包含了正常工作的代码。我希望有帮助