我有一个在反应中登录。
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>
)
}
我在onchange和submit中添加了字段验证,onchange验证工作正常,但显示错误。提交时的验证也很好,但当我尝试提交时,没有任何字段的变化,组件仍然没有显示错误。
我是新手,不知道这样做是否正确。先谢谢你了。
我把你的代码放在了 代码沙盒 而且似乎工作得很好。请注意,我删除了 className
属性和注释的东西,是没有必要的测试你的问题,如 redux
的进口。
由于我删除了 className
属性,这可能是一个 CSS
问题,你的错误 span
实际上已被渲染,但不可见 (查看浏览器的开发工具,以查看是否有 span
是真的不存在)。)
另外,如果你使用大量的表单,我建议你使用一个库,因为状态处理+验证可能会变得相当复杂,有很多解决方案。我写了我自己的库- 反应-流形 - 请随意查看。
编辑
这里的问题是,当你更新 error
使用 setError
你总是传递相同的对象引用。
// this is not doing a copy
// validationError will have the same reference as error
let validationError = error;
// ...
// following line will not trigger a rerender
setError(validationError);
因为 error
和 validationError
有相同的参照物。react
会认为没有发生变化,因此会造成 解救. 如果你在状态下使用复杂类型(如对象或数组),你总是需要创建一个新的引用,而不是适应以前的引用。
// this is an actual copy using the spread operator
// validationError will have different reference than error
let validationError = {...error};
// ...
// triggers rerender as expected
setError(validationError);
EDIT 2
我为 validate
使用更新后的 validationError
对象时,调用 validateForm
.
const validate = () => {
//..
let validationError = { ...error };
// ...
return validationError;
};
const onSubmit = e => {
// ...
const validationError = validate();
if (validateForm(validationError)) {
//...
}
};
见 更新代码沙盒.