[英]Invalid Hook Calls In Validation in ReactJS
I have a problem in implementing login validations in ReactJS.我在 ReactJS 中实现登录验证时遇到问题。 I'm using Material-UI and Formik and Yap.
我正在使用 Material-UI 和 Formik 和 Yap。 I have implemented it but it has an error, it says invalid hook call.
我已经实现了它,但它有一个错误,它说无效的钩子调用。 Hooks can only be called inside of the body of a function component.
钩子只能在 function 组件的主体内部调用。
Pls check my code below:请在下面检查我的代码:
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { makeStyles } from '@material-ui/styles';
import { Card, CardHeader, CardContent, CardActions, Divider, Button, TextField } from '@material-ui/core';
import { useSelector, useDispatch } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { login } from '../../../actions';
import AccountCircle from '@material-ui/icons/AccountCircle';
import InputAdornment from '@material-ui/core/InputAdornment';
import LockIcon from '@material-ui/icons/Lock';
import { withFormik } from 'formik';
const useStyles = makeStyles((theme) => ({
root: {},
cardHeader: {
backgroundColor: theme.palette.primary.main,
color: 'white',
display: 'flex',
justifyContent: 'center',
fontSize: '2rem',
padding: '15px',
},
textFieldSection: {
padding: '40px 40px 0 40px',
},
loginButtonSection: {
padding: '18px 40px 40px 40px',
},
loginButton: {
width: '100%',
height: '50px',
textTransform: 'none',
fontSize: '18px',
},
}));
const LoginForm = (props) => {
const { className, ...rest } = props;
const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
const referer = props.referer;
const dispatch = useDispatch();
const signIn = () => {
dispatch(login(values.username, values.password));
};
const { classes, values, touched, errors, isSubmitting, handleChange, handleBlur, handleSubmit } = props;
if (isLoggedIn) {
return <Redirect to={referer} />;
}
return (
<Card {...rest} className={clsx(classes.root, className)}>
<form onSubmit={handleSubmit}>
<CardHeader
title="LOGIN"
classes={{
title: classes.cardHeader,
}}
className={classes.cardHeader}
/>
<CardContent className={classes.textFieldSection}>
<TextField
fullWidth
label="Username"
name="username"
type="text"
variant="outlined"
value={values.username}
onChange={handleChange}
onBlur={handleBlur}
helperText={touched.username ? errors.username : ''}
error={touched.username && Boolean(errors.username)}
InputProps={{
endAdornment: (
<InputAdornment>
<AccountCircle />
</InputAdornment>
),
}}
/>
<TextField
fullWidth
label="Password"
name="password"
style={{ marginTop: '1rem' }}
type="password"
variant="outlined"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
helperText={touched.password ? errors.password : ''}
error={touched.password && Boolean(errors.password)}
InputProps={{
endAdornment: (
<InputAdornment>
<LockIcon />
</InputAdornment>
),
}}
/>
</CardContent>
<CardActions className={classes.loginButtonSection}>
<Button
color="primary"
variant="contained"
onClick={signIn}
className={classes.loginButton}
disabled={isSubmitting}
>
Log In
</Button>
</CardActions>
</form>
</Card>
);
};
let yup = require('yup');
const Form = withFormik({
mapPropsToValues: ({ username, password }) => {
return {
username: username || '',
password: password || '',
};
},
validationSchema: yup.object().shape({
username: yup.string().required('Required'),
password: yup.string().min(8, 'Password must contain at least 8 characters').required('Enter your password'),
}),
handleSubmit: (values, { setSubmitting }) => {
setTimeout(() => {
// submit to the server
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 1000);
},
})(LoginForm);
LoginForm.propTypes = {
className: PropTypes.string,
};
export default LoginForm(useStyles)(Form);
Create a higher-order React component class that passes props and form handlers (the "FormikBag") into your component derived from supplied options.
创建一个高阶 React 组件 class ,它将道具和表单处理程序(“FormikBag”)传递到从提供的选项派生的组件中。
Just export the Form
not LoginForm
.只需导出
Form
而不是LoginForm
。 Also to use classes
do const classes = useStyles();
还要使用
classes
做const classes = useStyles();
inside the component rather than passing it as props.在组件内部,而不是将其作为道具传递。
Working copy of your code is here 您的代码的工作副本在这里
Code Snippet代码片段
const useStyles = makeStyles(theme => ({
root: {},
cardHeader: {
// backgroundColor: theme.palette.primary.main,
backgroundColor: "blue",
color: "white",
display: "flex",
justifyContent: "center",
fontSize: "2rem",
padding: "15px"
},
textFieldSection: {
padding: "40px 40px 0 40px"
},
loginButtonSection: {
padding: "18px 40px 40px 40px"
},
loginButton: {
width: "100%",
height: "50px",
textTransform: "none",
fontSize: "18px"
}
}));
const LoginForm = props => {
const { className, ...rest } = props;
const classes = useStyles();
const isLoggedIn = true;
const referer = props.referer;
const signIn = () => {
console.log("signin");
};
const {
// classes,
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
if (isLoggedIn) {
// return <Redirect to={referer} />;
console.log("isLoggedIn", isLoggedIn);
}
return (
<Card {...rest} className={clsx(classes.root, className)}>
<form onSubmit={handleSubmit}>
<CardHeader
title="LOGIN"
classes={{
title: classes.cardHeader
}}
className={classes.cardHeader}
/>
<CardContent className={classes.textFieldSection}>
<TextField
fullWidth
label="Username"
name="username"
type="text"
variant="outlined"
value={values.username}
onChange={handleChange}
onBlur={handleBlur}
helperText={touched.username ? errors.username : ""}
error={touched.username && Boolean(errors.username)}
InputProps={{
endAdornment: (
<InputAdornment>
<AccountCircle />
</InputAdornment>
)
}}
/>
<TextField
fullWidth
label="Password"
name="password"
style={{ marginTop: "1rem" }}
type="password"
variant="outlined"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
helperText={touched.password ? errors.password : ""}
error={touched.password && Boolean(errors.password)}
InputProps={{
endAdornment: (
<InputAdornment>
<LockIcon />
</InputAdornment>
)
}}
/>
</CardContent>
<CardActions className={classes.loginButtonSection}>
<Button
type="submit" //<----------- see here
color="primary"
variant="contained"
onClick={signIn}
className={classes.loginButton}
disabled={isSubmitting}
>
Log In
</Button>
</CardActions>
</form>
</Card>
);
};
let yup = require("yup");
const Form = withFormik({
mapPropsToValues: ({ username, password }) => {
return {
username: username || "",
password: password || ""
};
},
validationSchema: yup.object().shape({
username: yup.string().required("Required"),
password: yup
.string()
.min(8, "Password must contain at least 8 characters")
.required("Enter your password")
}),
handleSubmit: (values, { setSubmitting }) => {
setTimeout(() => {
// submit to the server
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 1000);
}
})(LoginForm);
LoginForm.propTypes = {
className: PropTypes.string
};
// export default LoginForm(useStyles)(Form);
export default Form;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.