我正在构建一个与 Formik 和 Yup 库反应的基本形式。该表单包含两个字段,电子邮件和密码;那应该从用户那里获取值并将其打印在控制台中。 现在我面临的问题是 Hook 调用错误,即使我没有在我的代码中使用任何 Hook!
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. ..
2. ..
3. ..
我已经对这个错误进行了研究,并尝试了它建议的所有可能方法。没有任何帮助。我只运行一个反应版本,据我所知我也没有违反钩子规则。谁能帮我检测这里的问题?
我的代码:
登录表单.js
const validationSchema = Yup.object().shape({
email: Yup.string()
.email("Email is not valid")
.required("Email is required"),
password: Yup.string()
.min(6, "Minimum 6 characters required")
.required("Password is required"),
})
class LoginForm extends React.Component {
render() {
return (
<div>
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={validationSchema}
onSubmit={(values) => this.props.handleFormUpdate(values)}
>
<Form>
<label>
Email<Field type="email" name="email"></Field>
</label>
<ErrorMessage name="email" component="div"></ErrorMessage>
<label>
Password<Field type="password" name="password"></Field>
</label>
<ErrorMessage name="password" component="div"></ErrorMessage>
<button type="submit">Submit</button>
</Form>
</Formik>
</div>
);
}
}
export default LoginForm;
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
};
}
handleFormUpdate(values) {
console.log(values.email);
console.log(values.password);
}
render() {
return (
<div>
<LoginForm
handleFormUpdate={this.handleFormUpdate.bind(this)}
></LoginForm>
</div>
);
}
}
export default App;
这是因为
formik v2
是建立在 React Hooks 之上的。要解决这个问题,您需要将使用 formik 的类组件转换为功能组件。
这里是 formik. 的突破性变化的链接
[编辑] 或者你可以通过用高阶组件包装组件来使它与类组件一起工作
withFormik()
所以现在我已经解决了这个问题。我只需要将类组件转换为功能组件,就像上面提到的 adel 一样。 LoginForm.js 的新结构是:
const LoginForm = () => (
<div>
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={validationSchema}
onSubmit={(values) => this.props.handleFormUpdate(values)}
>
<Form>
<label>
Email<Field type="email" name="email"></Field>
</label>
<ErrorMessage name="email" component="div"></ErrorMessage>
<label>
Password<Field type="password" name="password"></Field>
</label>
<ErrorMessage name="password" component="div"></ErrorMessage>
<button type="submit">Submit</button>
</Form>
</Formik>
</div>
);
错误消失了!
我能够通过升级项目中的 React 版本来解决这个问题。检查项目上的 react 和 react-dom 的版本以及 node_modules 中的 formik。它们可能不同,这会导致无效挂钩调用错误。
或
您可能只是在类组件中使用 formik,这将不起作用。
React v.18.0 Compatible packages for Formik with material UI (mui) needs to be get installed.
Hence, This issue can be resolved using "formic-mui" package.
steps:
1. need to install packages "formik formik-mui @mui/material @emotion/react @emotion/styled"
2. then follow guidelines from here: [https://stackworx.github.io/formik-mui/docs/guide/getting-started][1]
3. After modifications, your code will look like this:
import * as React from 'react';
import { Formik, Field, Form, FormikHelpers } from 'formik';
import { Button, Grid, LinearProgress } from '@mui/material';
import * as yup from 'yup';
import { TextField } from 'formik-mui';
import TextareaAutosize from '@material-ui/core/TextareaAutosize/TextareaAutosize';
interface Values {
email: string;
password: string;
}
const CustomerDetails = () => {
return (
<div>
<h1>Customer Details</h1>
<Formik
initialValues={{
email: '',
password: '',
}}
validate={(values) => {
const errors: Partial<Values> = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
setSubmitting(false);
alert(JSON.stringify(values, null, 2));
}, 500);
}}
>
{({ submitForm, isSubmitting }) => (
<Form>
<Grid container spacing={1}>
<Grid item xs={4} sm={4}>
<Field
component={TextField}
name="customername"
type="customername"
label="Customer Name"
fullWidth
/>
</Grid>
<Grid item xs={12} sm={4}>
<Field
component={TextField}
type="telephone"
label="Telephone"
name="telephone"
fullWidth
/>
</Grid>
<Grid item xs={4} sm={4}>
<Field
component={TextField}
type="dob"
label="Date of Birth"
name="dob"
fullWidth
/>
</Grid>
<Grid item xs={12} sm={4}>
<Field
component={TextField}
type="alttelephone"
label="Alt Telephone"
name="alttelephone"
fullWidth
/>
</Grid>
<Grid item xs={12} sm={4}>
<Field
component={TextField}
type="alttelephone"
label="Alt Telephone"
name="alttelephone"
fullWidth
/>
</Grid>
<Grid item xs={4} sm={4}>
<Field
component={TextField}
name="email"
type="email"
label="Email"
fullWidth
/>
</Grid>
<Grid item xs={4} sm={4}>
<Field
component={TextField}
name="password"
type="password"
label="Password"
fullWidth
/>
</Grid>
{isSubmitting && <LinearProgress />}
<Grid item xs={12} sm={12}>
<Button
variant="contained"
color="primary"
disabled={isSubmitting}
onClick={submitForm}
>
Submit
</Button>
</Grid>
</Grid>
</Form>
)}
</Formik>
</div>
);
};
export default CustomerDetails;
[![enter image description here][1]][1]
此外,我的 Package.json 看起来像这样: