Leo*_*ssi 7 javascript validation reactjs yup formik
当我创建一个实体(在本例中为公司)时,我使用Formik和Yup来检查字段是否正确以及所有字段是否都已引入(全部都是必需的)。
当我创建一个实体时,它工作正常:只有在引入所有字段并且满足规则(目前仅针对电子邮件的一条规则)时,它才允许您创建它。
这是用于创建具有 2 个字段名称和电子邮件的新公司的代码:
import React from 'react';
import { Redirect } from 'react-router-dom';
import { Formik, Form, Field } from 'formik';
import { Input, Button, Label, Grid } from 'semantic-ui-react';
import { connect } from 'react-redux';
import * as Yup from 'yup';
import { Creators } from '../../../actions';
import Layout from '../../Layout/Layout';
class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
name: '',
contactMail: '',
redirectCreate: false,
redirectEdit: false,
edit: false,
};
}
componentDidMount() {
const {
getCompany,
location: { pathname },
} = this.props;
}
handleSubmit = values => {
const { createCompany, getCompanies } = this.props;
createCompany(values);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
render() {
let title = 'Create Company';
let buttonName = 'Create';
let submit = this.handleSubmitCreate;
const { redirectCreate, redirectEdit } = this.state;
if (redirectCreate) {
return <Redirect to="/companies" />;
}
const initialValues = {
name: '',
contactMail: '',
};
const requiredErrorMessage = 'This field is required';
const emailErrorMessage = 'Please enter a valid email address';
const validationSchema = Yup.object({
name: Yup.string().required(requiredErrorMessage),
contactMail: Yup.string()
.email(emailErrorMessage)
.required(requiredErrorMessage),
});
return (
<Layout>
<div>
<Button type="submit" form="amazing">
Create company
</Button>
<Button onClick={() => this.props.history.goBack()}>Discard</Button>
<div>Create company</div>
</div>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ values, errors, touched, setValues }) => (
<Form id="amazing">
<Grid columns={2}>
<Grid.Column>
<Label>Company Name</Label>
<Field name="name" as={Input} placeholder="Hello" />
<div>{touched.name && errors.name ? errors.name : null}</div>
</Grid.Column>
<Grid.Column>
<Label>Contact Mail</Label>
<Field
name="contactMail"
as={Input}
placeholder="johnappleseed@hello.com"
/>
<div>
{touched.contactMail && errors.contactMail
? errors.contactMail
: null}
</div>
</Grid.Column>
</Grid>
</Form>
)}
</Formik>
</Layout>
);
}
}
const mapStateToProps = state => ({
companies: state.companies.companies,
company: state.companies.selectedCompany,
query: state.companies.query,
});
const mapDispatchToProps = {
getCompanies: Creators.getCompaniesRequest,
createCompany: Creators.createCompanyRequest,
getCompany: Creators.getCompanyRequest,
updateCompany: Creators.updateCompanyRequest,
};
export default connect(mapStateToProps, mapDispatchToProps)(CreateCompanyForm);
Run Code Online (Sandbox Code Playgroud)
当我想编辑公司时出现问题。因此,当有人单击公司的编辑按钮时,它应该打开该公司,其中所有字段都包含应可编辑的当前值。
为了获取这些当前值,我正在使用状态,例如可以从 访问电子邮件this.state.email并更改添加的值onChange方法。
可以在文本输入中修改这些值。但是,它会触发 Yup 消息,表明即使其中有数据,该字段也是必需的 - 为什么会发生这种情况?该字段不为空,这是必须显示该消息的情况。
当然,当我单击保存实体时,它不会更新实体,因为它需要这些字段。
这是代码:
import React from 'react';
...
class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
name: '',
contactMail: '',
redirectCreate: false,
redirectEdit: false,
edit: false,
};
}
componentDidMount() {
const {
getCompany,
location: { pathname },
} = this.props;
if (pathname.substring(11) !== 'create') { // checks the URL if it is in edit mode
getCompany(pathname.substring(16));
this.setState({
edit: true,
});
this.setState({
name: this.props.company.name,
contactMail: this.props.company.contactMail,
});
}
}
onChange = (e, { name, value }) => { // method to update the state with modified value in input
this.setState({ [name]: value });
};
handleSubmit = values => {
const { createCompany, getCompanies } = this.props;
createCompany(values);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
handleSubmitEdit = e => {
e.preventDefault();
const { name, contactMail } = this.state;
const { updateCompany } = this.props;
updateCompany(this.props.company._id, {
name,
contactMail,
});
this.setState({ redirectEdit: true });
};
render() {
let title = 'Create Company';
let buttonName = 'Create';
let submit = this.handleSubmitCreate;
const { redirectCreate, redirectEdit } = this.state;
if (redirectCreate) {
return <Redirect to="/companies" />;
}
if (redirectEdit) {
return <Redirect to={`/companies/${this.props.company._id}`} />;
}
if (this.state.edit) {
title = 'Edit Company';
buttonName = 'Edit';
submit = this.handleSubmitEdit;
}
const initialValues = {
name: '',
contactMail: '',
};
const requiredErrorMessage = 'This field is required';
const emailErrorMessage = 'Please enter a valid email address';
const validationSchema = Yup.object({
name: Yup.string().required(requiredErrorMessage),
contactMail: Yup.string()
.email(emailErrorMessage)
.required(requiredErrorMessage),
});
return (
<Layout>
<div>
<Button type="submit" form="amazing">
Create company
</Button>
<Button onClick={() => this.props.history.goBack()}>Discard</Button>
<div>Create company</div>
</div>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ values, errors, touched, setValues }) => (
<Form id="amazing">
<Grid columns={2}>
<Grid.Column>
<Label>Company Name</Label>
<Field
name="name"
as={Input}
placeholder="Hello"
value={this.state.name || ''} // takes the value from the state
onChange={this.onChange} // does the changing
/>
<div>{touched.name && errors.name ? errors.name : null}</div>
</Grid.Column>
<Grid.Column>
<Label>Contact Mail</Label>
<Field
name="contactMail"
as={Input}
placeholder="johnappleseed@hello.com"
value={this.state.contactMail || ''} // takes the value from the state
onChange={this.contactMail} // does the changing
/>
<div>
{touched.contactMail && errors.contactMail
? errors.contactMail
: null}
</div>
</Grid.Column>
</Grid>
</Form>
)}
</Formik>
</Layout>
);
}
}
...
export default connect(mapStateToProps, mapDispatchToProps)(CreateCompanyForm);
Run Code Online (Sandbox Code Playgroud)
有关如何解决此问题并使字段可编辑并'This field is required'在字段已有数据时删除消息的任何想法吗?
你需要做 3 个小改变:
\n1. 您的初始值始终设置为:
\nconst initialValues = {\n name: \'\',\n contactMail: \'\',\n};\nRun Code Online (Sandbox Code Playgroud)\n您需要将其更改为:
\nconst initialValues = {\n name: this.state.name,\n contactMail: this.state.contactMail,\n};\nRun Code Online (Sandbox Code Playgroud)\n2. 添加enableReinitialize到Formik
即使更改 n\xc2\xba 1,您的提交仍然会抛出错误,因为在创建组件时,Formik会使用构造函数中的值呈现 \xc2\xb4s:
const initialValues = {\n name: \'\',\n contactMail: \'\',\n};\nRun Code Online (Sandbox Code Playgroud)\n当您更改内部状态时componentDidMount,Formik不会使用更新值重新初始化:
componentDidMount() {\n const {\n getCompany,\n location: { pathname },\n } = this.props;\n if (pathname.substring(11) !== \'create\') { // checks the URL if it is in edit mode \n getCompany(pathname.substring(16));\n this.setState({\n edit: true,\n });\n this.setState({\n name: this.props.company.name,\n contactMail: this.props.company.contactMail,\n });\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n因此,要重新初始化 formik,您需要添加enableReinitialize如下内容:
const initialValues = {\n name: this.state.name,\n contactMail: this.state.contactMail,\n};\nRun Code Online (Sandbox Code Playgroud)\n3. 使用enableReinitialize,Formik将触发对模糊和更改的验证。为了避免这种情况,你可以添加validateOnChangeandvalidateOnBlur为 false:
this.state = {\n name: "",\n contactMail: "",\n redirectCreate: false,\n redirectEdit: false,\n edit: false,\n };\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
7097 次 |
| 最近记录: |