页面正确地呈现了输入,但是错误似乎仅出现在第二个呈现器上,即使它们在第一个呈现器上显示为useForm状态也是如此。
因此,对于密码字段,我输入一个字符,并且useForm的状态更改为{password: "Must be at.....}
,但是直到我输入另一个字符后,屏幕才会更新为显示errors.password
。
// nodejs library that concatenates classes
// reactstrap components
import {
Button,
Card,
CardBody,
CardHeader,
Col,
Container,
Form,
FormFeedback,
FormGroup,
Input,
Row
} from "reactstrap";
import {register} from "apiCalls/AuthRequests";
import useForm from "hooks/AuthHooks";
import {registerFormValidation} from "components/validation/AuthFormValidation";
function RegisterForm(props) {
const [loading, setLoading] = useState(false);
const {values, handleChange, handleSubmit, errors, setErrors} = useForm(submit, registerFormValidation);
const emailRef = useRef(null);
const passwordRef = useRef(null);
const accessCodeRef = useRef(null);
async function submit() {
setLoading(true);
const response = await register(values.email, values.password, values.accessCode);
if (response.ok) {
} else if (response.status === 422) {
if ("access_code" in response.data) {
accessCodeRef.current.focus();
setErrors({accessCode: response.data.access_code});
}
if ("email" in response.data) {
setErrors({email: response.data.email});
emailRef.current.focus();
}
if ("password" in response.data) {
setErrors({password: response.data.password});
passwordRef.current.focus();
}
}
setLoading(false)
}
useEffect(() => {
console.log(errors);
});
return (
<>
<div className="content">
<Container className="pb-5">
<Row>
<Col lg="6" md="8" className="ml-auto mr-auto">
<Card className="bg-secondary border-0">
<CardHeader className="bg-transparent">
<div className="text-center">
<h2>Register</h2>
</div>
</CardHeader>
<CardBody className="px-lg-5 py-lg-5">
<Form role="form" onSubmit={handleSubmit}>
<FormGroup>
<label
className="form-control-label"
>
Email
</label>
<Input
name="email"
type="email"
innerRef={emailRef}
value={values.email || ""}
onChange={handleChange}
invalid={!!errors.email}
required
/>
<FormFeedback>{errors.email}</FormFeedback>
</FormGroup>
<FormGroup>
<label
className="form-control-label"
>
Password
</label>
<Input
name="password"
type="password"
innerRef={passwordRef}
value={values.password || ""}
onChange={handleChange}
invalid={!!errors.password}
required
/>
<FormFeedback>{errors.password}</FormFeedback>
</FormGroup>
<FormGroup>
<label
className="form-control-label"
>
Access Code
</label>
<Input
name="accessCode"
type="text"
innerRef={accessCodeRef}
value={values.accessCode || ''}
onChange={handleChange}
invalid={!!errors.accessCode}
required
/>
<FormFeedback>{errors.accessCode}</FormFeedback>
</FormGroup>
<Row className="my-4">
<Col xs="12">
<div
className="custom-control custom-control-alternative custom-checkbox">
<input
className="custom-control-input"
id="customCheckRegister"
type="checkbox"
required
/>
<label
className="custom-control-label"
htmlFor="customCheckRegister"
>
<span className="text-muted">
I agree with the{" "}
<a
href=""
target="_blank"
rel="noopener noreferrer"
>
Privacy Policy
</a>
</span>
</label>
</div>
</Col>
</Row>
<div className="text-center">
<Button disabled={loading} className="mt-4" color="info" type="submit">
Create account
</Button>
</div>
</Form>
</CardBody>
</Card>
</Col>
<Col md="4" className="ml-auto mr-auto">
<h2>Being a photographer is easier with <b className="text-primary">FOCAL</b></h2>
<ul>
<li>
<h4>Focal is great</h4>
</li>
<li>
<h4>Save time</h4>
</li>
<li>
<h4>More customers</h4>
</li>
</ul>
</Col>
</Row>
</Container>
</div>
</>
);
}
export default RegisterForm;
const useForm = (callback, validate) => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = (event) => {
if (event) event.preventDefault();
setIsSubmitting(true);
};
useEffect(() => {
if (Object.keys(errors).length === 0 && isSubmitting) {
callback();
setIsSubmitting(false);
}
}, [callback, errors, isSubmitting]);
useEffect(() => {
setErrors(validate(values, errors));
}, [validate, values, errors]);
const handleChange = (event) => {
event.persist();
setValues(values => ({...values, [event.target.name]: event.target.value}));
setErrors(validate(values, errors));
};
return {
handleChange,
handleSubmit,
setErrors,
values,
errors
}
};
export default useForm;
export function registerFormValidation(values, errors) {
if (values.email === ""){
delete errors.email;
}
if (values.password) {
if (!verifyLength(values.password, PASSWORD_LENGTH)){
errors.password = "Password must be greater than 8 Characters";
} else {
delete errors.password;
}
}
if (values.accessCode === "") {
delete values.accessCode;
}
return errors
}```
答案 0 :(得分:1)
我很高兴使用自定义钩子很有趣,但是表单无处不在,并且有可靠的可靠方法来使用它们。恕我直言Formik可能是最好的。
有了三个字段,您可以实现以下内容:
import React from 'react';
import { Formik } from 'formik';
const BasicExample = () => (
<div>
<Formik
initialValues={{ email: '', password: '', accessCode: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
render={props => (
<form onSubmit={props.handleSubmit}>
<input
type="email"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.email}
name="email"
/>
{props.errors.email && <div id="feedback">{props.errors.email}</div>}
<input
type="password"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.password}
name="password"
/>
{props.errors.password && <div id="feedback">{props.errors.password}</div>}
<input
type="text"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.accessCode}
name="accessCode"
/>
{props.errors.accessCode && <div id="feedback">{props.errors.acessCode}</div>}
<button type="submit">Submit</button>
</form>
)}
/>
</div>
);
请注意,以上内容仅来自内存-从某种程度上讲,这很简单。当initialValues
提供给Formik时,您可以构建复杂的组件层次结构而不必传递表单状态,但这只是各种好处之一。
答案 1 :(得分:0)
我有一个假设。
在registerFormValidation中不会修改错误对象。每次创建一个新的。
答案 2 :(得分:0)
已修复:
const useForm = (callback, validate) => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const handleSubmit = (event) => {
if (event) event.preventDefault();
if (Object.keys(errors).length === 0){
callback();
}
};
const handleChange = (event) => {
event.persist();
setValues(values => ({...values, [event.target.name]: event.target.value}));
setErrors(validate({[event.target.name]: event.target.value}, errors));
};
return {
handleChange,
handleSubmit,
setErrors,
values,
errors
}
};
export default useForm;
摆脱useEffect!