如果处于编辑模式,则从状态设置 Formik 中的 initialVariables
Set initialVariables in Formik from state if it is in edit mode
我正在使用 Formik 来验证一些数据。它应该创建新实体时工作正常,但当我想编辑实体时出现问题。
编辑模式必须从状态激活(this.state.edit === true),实体的数据也存储在状态上,例如this.state.name在那里有一个字符串值.
我在 render 中放置了一个控制台日志,问题是日志打印了好几次,第一次在 this.sate.name 上打印了空字符串并且 this.state.edit 的值为 false。下一个打印是正确的,此编辑对 true 和 name 包含一个值。
代码如下:
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';
class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
name: '',
redirectCreate: false,
redirectEdit: false,
edit: false,
};
}
componentDidMount() {
const {
getCompany,
getCompanies,
location: { pathname },
} = this.props;
getCompanies({
name: '',
});
if (pathname.substring(11) !== 'create') {
getCompany(pathname.substring(16));
this.setState({
edit: true,
});
this.setState({
name: this.props.company.name,
});
}
}
handleSubmitCreate = e => {
e.preventDefault();
const { createCompany, getCompanies } = this.props;
createCompany(this.state);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
handleSubmit = values => {
const { createCompany, getCompanies } = this.props;
createCompany(values);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
handleSubmitEdit = e => {
e.preventDefault();
const { name } = this.state;
const { updateCompany } = this.props;
updateCompany(this.props.company._id, {
name,
});
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;
}
console.log('state: ', this.state); // first time it is empty, next times it has data
let initialValues = {};
if (this.state.edit) {
initialValues = {
name: this.state.name,
};
} else {
initialValues = {
name: '',
};
}
const validationSchema = Yup.object({
name: Yup.string().required('This field is required'),
});
return (
<>
<Button type="submit" form="amazing">
create company
</Button>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ values, errors, touched, setValues, setFieldValue }) => (
<Form id="amazing">
<Grid>
<Grid.Column>
<Label>Company name</Label>
<Field name="name" as={Input} placeholder="write a name" />
<div>{touched.name && errors.name ? errors.name : null}</div>
</Grid.Column>
</Grid>
<Button type="submit" floated="right" form="amazing">
{buttonName} company
</Button>
</Form>
)}
</Formik>
</>
);
}
}
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);
我将整个文件放在这里是为了获得更多上下文。是否可以使用 this.state.name 中的值设置 name
的初始值并将其放入输入字段中?
默认情况下,如果初始值发生变化,Formik 不会re-render。您可以将 enableReinitialize
属性传递给 Formik 组件以允许它。
正如您在评论中所说,第一次呈现时,它没有数据,因此它确实用空值初始化了 Formik。使用该道具,如果初始值发生变化,它应该 re-render。
https://formik.org/docs/api/formik#enablereinitialize-boolean
我正在使用 Formik 来验证一些数据。它应该创建新实体时工作正常,但当我想编辑实体时出现问题。
编辑模式必须从状态激活(this.state.edit === true),实体的数据也存储在状态上,例如this.state.name在那里有一个字符串值.
我在 render 中放置了一个控制台日志,问题是日志打印了好几次,第一次在 this.sate.name 上打印了空字符串并且 this.state.edit 的值为 false。下一个打印是正确的,此编辑对 true 和 name 包含一个值。
代码如下:
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';
class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
name: '',
redirectCreate: false,
redirectEdit: false,
edit: false,
};
}
componentDidMount() {
const {
getCompany,
getCompanies,
location: { pathname },
} = this.props;
getCompanies({
name: '',
});
if (pathname.substring(11) !== 'create') {
getCompany(pathname.substring(16));
this.setState({
edit: true,
});
this.setState({
name: this.props.company.name,
});
}
}
handleSubmitCreate = e => {
e.preventDefault();
const { createCompany, getCompanies } = this.props;
createCompany(this.state);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
handleSubmit = values => {
const { createCompany, getCompanies } = this.props;
createCompany(values);
this.setState({ redirectCreate: true });
getCompanies(this.props.query);
};
handleSubmitEdit = e => {
e.preventDefault();
const { name } = this.state;
const { updateCompany } = this.props;
updateCompany(this.props.company._id, {
name,
});
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;
}
console.log('state: ', this.state); // first time it is empty, next times it has data
let initialValues = {};
if (this.state.edit) {
initialValues = {
name: this.state.name,
};
} else {
initialValues = {
name: '',
};
}
const validationSchema = Yup.object({
name: Yup.string().required('This field is required'),
});
return (
<>
<Button type="submit" form="amazing">
create company
</Button>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ values, errors, touched, setValues, setFieldValue }) => (
<Form id="amazing">
<Grid>
<Grid.Column>
<Label>Company name</Label>
<Field name="name" as={Input} placeholder="write a name" />
<div>{touched.name && errors.name ? errors.name : null}</div>
</Grid.Column>
</Grid>
<Button type="submit" floated="right" form="amazing">
{buttonName} company
</Button>
</Form>
)}
</Formik>
</>
);
}
}
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);
我将整个文件放在这里是为了获得更多上下文。是否可以使用 this.state.name 中的值设置 name
的初始值并将其放入输入字段中?
默认情况下,如果初始值发生变化,Formik 不会re-render。您可以将 enableReinitialize
属性传递给 Formik 组件以允许它。
正如您在评论中所说,第一次呈现时,它没有数据,因此它确实用空值初始化了 Formik。使用该道具,如果初始值发生变化,它应该 re-render。
https://formik.org/docs/api/formik#enablereinitialize-boolean