我正在尝试创建一个函数,该函数将在用户每次输入字段时递增。
我目前有一个父组件,该组件的状态被设置为0。我的孩子组件是一个Formik容器组件,用于保存和处理我的字段。
//父组件
import React, { Component } from "react";
import Formik from "./Formik";
export default class BountyPage extends Component {
state = {
total: 0
};
render() {
return (
<div className="bountyPage">
<div className="total_container">
<p className="total_title pt-2">SERV</p>
<h1 className="total_sub">{this.state.total}</h1>
</div>
<Formik />
</div>
);
}
}
//子组件
const Formik = ({ values, errors, touched, isSubmitting,
setFieldValue }) => (
<Form className="form">
{touched.lastName &&
values.lastName &&
touched.firstName &&
values.firstName ? (
<Row>
<Col className="result_text pulse animated p-4">
<b>Welcome</b>{" "}
<span
className="clickable_text"
onClick={async () => {
await setFieldValue("firstName", "");
await setFieldValue("lastName", "");
}}
>
{values.firstName} {values.lastName}
</span>
</Col>
</Row>
) : (
<Row className="glow_form p-1">
<Col md={6}>
<FormGroup>
<Label for="firstName">First Name</Label>
<Field
type="firstName"
name="firstName"
placeholder="ie. John"
className="form-control"
/>
{touched.firstName && errors.firstName && <p>
{errors.firstName}</p>}
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label for="lastName">Last Name</Label>
<Field
type="lastName"
name="lastName"
placeholder="ie. Doe"
className="form-control"
/>
{touched.lastName && errors.lastName && <p>
{errors.lastName}</p>}
</FormGroup>
</Col>
</Row>
)}
<Row className="glow_form pt-1">
<Col>
<FormGroup>
<Label for="email">Bittrex Email Address</Label>
<Field
type="email"
name="email"
placeholder="ie. example@domain.com"
className="form-control"
/>
{touched.email && errors.email && <p>{errors.email}</p>}
</FormGroup>
</Col>
</Row>
<Row>
<Col className="col_container">
<FormGroup>
<div className="switch_container">
<p>I’m a business owner</p>
<label className="switch">
<Field type="checkbox" name="switch1" checked=
{values.switch1} />
<span className="slider round" />
</label>
</div>
</FormGroup>
{values.switch1 && (
<Row className="bounceInDown animated">
<Col md={6}>
<FormGroup>
<Field
type="text"
name="industryText"
placeholder="ie. Automotive"
className="form-control"
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Field
type="number"
name="locationText"
placeholder="ie. 1-2"
className="form-control"
/>
</FormGroup>
</Col>
</Row>
)}
</Col>
</Row>
{values.firstName && values.lastName ? (
<Row>
<Col className="text-center">
{values.email ? (
<span>
<Button
type="submit"
disabled={isSubmitting}
className="submit_btn"
>
Review
</Button>
<hr />
</span>
) : (
<span>
<Button
type="submit"
disabled={isSubmitting}
className="submit_btn"
>
Submit
</Button>
<hr />
</span>
)}
</Col>
</Row>
) : (
""
)}
</Form>
);
export default withFormik({
mapPropsToValues({
firstName,
lastName,
email,
switch1,
industryText,
locationText,
checkbox
}) {
return {
firstName: firstName || "",
lastName: lastName || "",
email: email || "",
switch1: switch1 || false,
industryText: industryText || "",
locationText: locationText || "",
checkbox: checkbox || false
};
},
validationSchema: Yup.object().shape({
firstName: Yup.string()
.max(40, "Please enter no more than 40 characters")
.required("Please enter your first name"),
lastName: Yup.string()
.max(40, "Please enter no more than 40 characters")
.required("Please enter a last name"),
email: Yup.string()
.email("Please enter a valid email")
.required("Please enter an email")
}),
handleSubmit(values, { resetForm }) {
console.log(values);
resetForm();
}
})(Formik);
如何从父组件中的formik容器访问“值”,以便可以递增计数器状态,以便每次完成字段时动态计数器都会递增?我尝试创建一个回调函数,但由于我不知道formik组件容器的工作原理,因此无法正常传递该函数。
答案 0 :(得分:1)
在这里:您也可以转到我创建的此沙箱:
https://codesandbox.io/s/0ovjx025lp
import React from "react";
import { render } from "react-dom";
import { Formik } from "formik";
import * as Yup from "yup";
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
increment = () => {
this.setState({
counter: this.state.counter + 1
});
};
decrement = () => {
this.setState({
counter: this.state.counter - 1
});
};
render() {
return (
<React.Fragment>
<h3>Counter:: {this.state.counter}</h3>
<App handleIncrement={this.increment} />
</React.Fragment>
);
}
}
const App = originalProps => (
<div className="app">
<h1>
Basic{" "}
<a
href="https://github.com/jaredpalmer/formik"
target="_blank"
rel="noopener"
>
Formik
</a>{" "}
Demo
</h1>
<Formik
initialValues={{ email: "" }}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 500);
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required")
})}
>
{props => {
const {
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
handleReset
} = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email" style={{ display: "block" }}>
Email
</label>
<input
id="email"
placeholder="Enter your email"
type="text"
value={values.email}
onChange={e => {
originalProps.handleIncrement();
handleChange(e);
}}
onBlur={handleBlur}
className={
errors.email && touched.email
? "text-input error"
: "text-input"
}
/>
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
<button
type="button"
className="outline"
onClick={handleReset}
disabled={!dirty || isSubmitting}
>
Reset
</button>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
);
}}
</Formik>
</div>
);
render(<Parent />, document.getElementById("root"));
答案 1 :(得分:1)
只需仔细看一下Formik文档即可。他们有一个非常全面的示例,您可以在这里做什么:https://jaredpalmer.com/formik/docs/api/field#validate
另一方面,我为您创建了一个沙箱,以使您了解如何复制所需的内容。
父项:
import React from "react";
import Child from "./Child";
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
handleIncrement = event => {
this.setState({
counter: this.state.counter + 1
});
};
handleDecrement = event => {
this.setState({
counter: this.state.counter - 1
});
};
render() {
return (
<div>
<h3>Parent Counter: {this.state.counter}</h3>
<Child
onComplete={this.handleIncrement}
onInvalidate={this.handleDecrement}
/>
</div>
);
}
}
export default Parent;
子组件:
import React from "react";
import { Formik, Form, Field } from "formik";
class Child extends React.Component {
state = {
emailValid: false,
passwordValid: false
};
//value is passed in implicitly from the Field
validateEmail = value => {
//insert email logic here
if (value.includes("@") && !this.state.emailValid) {
this.setState({
emailValid: true
});
//if field is complete then increase counter on parent
this.props.onComplete();
} else if (!value.includes("@") && this.state.emailValid) {
this.setState({
emailValid: false
});
//if field was valid and no longer is valid
this.props.onInvalidate();
}
};
validatePassword = value => {
//insert password logic here
if (value.length >= 6 && !this.state.passwordValid) {
this.setState({
passwordValid: true
});
this.props.onComplete();
} else if (value.length < 6 && this.state.passwordValid) {
this.setState({
passwordValid: false
});
//if field was valid and no longer is valid
this.props.onInvalidate();
}
};
handleSubmit = event => {
event.preventDefault();
};
render() {
return (
<div className="app">
<Formik
initialValues={{ email: "", username: "" }}
onSubmit={this.handleSubmit}
>
{({ errors, touched }) => (
<Form>
<Field validate={this.validateEmail} name="email" type="email" />
{errors.email && touched.email ? <div>{errors.email}</div> : null}
<Field validate={this.validatePassword} name="password" />
{errors.password && touched.password ? (
<div>{errors.username}</div>
) : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);
}
}
export default Child;
https://codesandbox.io/s/8x736oqwq0
您最终将不得不根据您的逻辑对其进行修改。如果您有任何问题,请告诉我。 :)