我刚刚重组了授权表单组件,以将状态处理逻辑拉到一个自定义钩子中,以便可以在其他地方重用它。在此之前,提交我的表单不会触发重新呈现(例如,如果存在验证错误),但是现在可以。需要说明的是,页面实际上并没有重新加载/刷新(因此我认为这不是来自默认的表单提交行为),但是背景图像(来自更高级别的容器组件)确实可以重新渲染。
AuthForm.js
const AuthForm = ({ buttonText, formType, onAuth, history, ...props }) => {
const submitData = () => {
onAuth(formType, values, history);
}
const {
values,
errors,
handleChange,
handleSubmit,
} = useForm(submitData, validate);
return (
<Form onSubmit={handleSubmit}>
<FlexContainer flexDirection="column" justify="space-between" >
<FlexContainer flexDirection="column" >
<TextInput
id="email"
name="email"
onChange={handleChange}
value={values.email || ''}
placeholder="Email"
onFocus={(e) => e.target.placeholder = ""}
onBlur={(e) => e.target.placeholder = "Email"}
/>
{errors.email && <ErrorMessage>{errors.email}</ErrorMessage>}
<TextInput
id="password"
name="password"
onChange={handleChange}
type="password"
value={values.password || ''}
placeholder="Password"
onFocus={(e) => e.target.placeholder = ""}
onBlur={(e) => e.target.placeholder = "Password"}
/>
{errors.password && <ErrorMessage>{errors.password}</ErrorMessage>}
</FlexContainer>
<FlexContainer flexDirection='column' >
<Button type="submit" buttonText={buttonText} buttonSize="large"/>
</FlexContainer>
</FlexContainer>
</Form>
)
};
...
function validate(values) {
let errors = {};
if (!values.email) {
errors.email = 'Email address is required';
} else if (!/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/.test(values.email)) {
errors.email = 'Email address is invalid';
}
if (!values.password) {
errors.password = 'Password is required';
} else if (values.password.length < 8) {
errors.password = 'Password must be 8 or more characters';
}
return errors;
};
export default AuthForm;
useForm.js(自定义钩子)-取自this article
的修改const useForm = (callback, validate) => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
if (Object.keys(errors).length === 0 && isSubmitting) {
callback();
}
else if (isSubmitting) {
setValues({});
}
}, [errors]);
const handleSubmit = (e) => {
e.preventDefault();
setErrors(validate(values));
setIsSubmitting(true);
};
const handleChange = (event) => {
event.persist();
setValues(values => ({ ...values, [event.target.name]: event.target.value }));
};
return {
handleChange,
handleSubmit,
values,
errors,
}
};
export default useForm;
鉴于大多数代码是相同的(只是重新定位到了一个钩子),我不知道为什么它会导致在树的上方重新渲染。
AuthForm由AuthContainer呈现,而AuthContainer由AuthPage呈现。 AuthPage是渲染我的背景图像的地方。
AuthPage.js
const Background = styled.div`
background-image: url('myimage.jpg');
background-repeat: no-repeat;
background-size: cover;
min-height: 90vh;
`
const AuthPage = (props) => (
<Background>
<FlexContainer justify="space-evenly" padding="100px 40px 0 40px" wrap="nowrap">
<AuthContainer {...props}/>
<AsideContainer {...props} />
</FlexContainer>
</Background>
)
export default AuthPage;