禁用的 Formik 字段的重置值
Reset value of disabled Formik Field
我正在尝试 clear/reset 复选框禁用后的值。我最初认为我是通过使用 React 条件并将值设置为空字符串来实现此目的的,但如果复选框在被禁用之前已被激活,那么该值仍会被提交。这种行为似乎不正确,因为我的印象是未提交禁用的输入字段值?
React 条件表示如果表单被禁用,则复选框的值应该为空。
我正在使用 Formik 处理带有 Yup 模式验证的表单。
下面是我的表单的完整代码。
提前谢谢你。
import axios from "axios";
import * as Yup from "yup";
import Head from "next/head";
import Link from "next/link";
import Router from "next/router";
import { useState } from "react";
import Error from "../components/error";
import Layout from "../components/layout";
import Button from "react-bootstrap/Button";
import Spinner from "react-bootstrap/Spinner";
import { Formik, Form, Field, ErrorMessage } from "formik";
var instagram = false;
var twitter = false;
var github = false;
const validationSchema = Yup.object({
firstName: Yup.string()
.max(15, "Must be 15 characters or less"),
email: Yup.string().email("Invalid email address").required("Required"),
username: Yup.string()
.test(
'valid-instagram', "Instagram: may contain only alphanumeric characters, periods, and underscores", function (username){
var instagramRegex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/);
var instagramRes = instagramRegex.test(username)
if (instagramRes) { // if res is true then the username is valid and the switch can be enabled
instagram = false;
return true // return true to tell Yup the field is valid
} else {
instagram = true;
return true // true removes error message
}
}
)
.test(
'valid-twitter', "Twitter: may only contain alphanumeric characters or underscores", function (username){
var twitterRegex = new RegExp(/^[A-Za-z0-9_]{1,15}$/);
var twitterRes = twitterRegex.test(username)
if (twitterRes) { // if res is true then the username is valid and the switch can be enabled
twitter = false;
return true // return true to tell Yup the field is valid
} else {
twitter = true;
return true // true removes error message
}
}
)
.test(
'valid-github', "GitHub: may only contain alphanumeric characters or single hyphens", function (username){
var githubRegex = new RegExp(/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i);
var githubRes = githubRegex.test(username)
if (githubRes) { // if res is true then the username is valid and the switch can be enabled
github = false;
return true // return true to tell Yup the field is valid
} else {
github = true;
return true // true removes error message
}
}
)
.required("Required"),
acceptTerms: Yup.boolean()
.required("Required")
.oneOf([true], "You must accept the terms and conditions."),
switchGroup: Yup.array().required("At least one option must be selected"),
});
const initialValues = {
firstName: "",
email: "",
username: "",
acceptTerms: false, // added for our checkbox
switchGroup: [], // array for switches
};
export default function Signup() {
const [error, setError] = useState("");
return (
<Layout>
<Head>
<title>Signup - Notify.is</title>
</Head>
<div className="container-center">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
const data = new URLSearchParams(values);
const res = await axios
.post("http://localhost:8080/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>
{({ touched, errors, isSubmitting }) => (
<Form className="form">
<h1 className="display-4 pb-3">Get notified</h1>
<div className="form-label-group">
<Field
type="text"
name="firstName"
id="firstName"
placeholder="First name"
className={`form-control ${
touched.firstName && errors.firstName
? "is-invalid"
: null
}`}
/>
<label htmlFor="firstname">First name</label>
<small id="nameHelp" className="form-text text-muted">
Optional
</small>
</div>
<div className="form-label-group">
<Field
type="email"
name="email"
id="email"
placeholder="Email address"
className={`form-control ${
touched.email && errors.email ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="email"
className="invalid-feedback"
/>
<small id="emailHelp" className="form-text text-muted">
We'll never share your email with anyone else.
</small>
<label htmlFor="email">Email address</label>
</div>
<div className="form-label-group">
<Field
type="text"
name="username"
id="username"
autoCorrect="off"
autoCapitalize="none"
placeholder="Username"
className={`form-control ${
touched.username && errors.username ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="username"
className="invalid-feedback"
/>
<small id="usernameHelp" className="form-text text-muted">
The unavailable username you want.
</small>
<label htmlFor="username">Username</label>
</div>
<div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="instagram-switch"
value={instagram ? "" : "instagram"}
disabled={instagram}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="instagram-switch"
>
Instagram
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="twitter-switch"
value={twitter ? "" : "twitter"}
disabled={twitter}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="twitter-switch"
>
Twitter
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="github-switch"
value={github ? "" : "github"}
disabled={github}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="github-switch"
>
GitHub
</label>
<ErrorMessage
component="div"
name="switchGroup"
className="invalid-feedback"
/>
</div>
<small id="usernameHelp" className="form-text text-muted">
The service(s) we should check with.
</small>
</div>
<div className="custom-control custom-checkbox pt-3 mb-1">
<Field
type="checkbox"
name="acceptTerms"
id="acceptTerms"
className={`custom-control-input ${
touched.acceptTerms && errors.acceptTerms
? "is-invalid"
: null
}`}
/>
<label htmlFor="acceptTerms" className="custom-control-label">
By checking this box you agree to our:
</label>
<ErrorMessage
component="div"
name="acceptTerms"
className="invalid-feedback"
/>
</div>
<span className="grey termslabel">
<Link href="/tos">
<a className="terms" target="_blank">
Terms of Use
</a>
</Link>{" "}
and{" "}
<Link href="/privacy">
<a className="terms" target="_blank">
Privacy Policy
</a>
</Link>
</span>
<Button
className="btn-lg btn-primary btn-block mt-4"
variant="primary"
disabled={isSubmitting, error}
type="submit"
>
{isSubmitting && (
<Spinner
as="span"
animation="grow"
size="lg"
role="status"
aria-hidden="true"
/>
)}
{isSubmitting && <span> Submitting...</span>}
{!isSubmitting && <span>Sign up</span>}
</Button>
{error ? <Error error={error} /> : null}
<p className="mt-4 mb-3 text-muted text-center">
© Notify.is 2020
</p>
</Form>
)}
</Formik>
</div>
<style jsx>
{`
.display-4 {
font-weight: 700;
}
.terms {
text-decoration: underline;
}
.terms:hover {
text-decoration: none;
}
`}
</style>
</Layout>
);
}
检查 FieldArray 组件。它的渲染道具为来自 fieldArrays 的 adding/removing 值提供了一个 arrayHelper
。
我最终设法以不同于最初预期的方式完成了我想做的事情,但效果很好。
使用基于是否应禁用字段更改值的布尔变量,我为 Formik onSubmit prop 中的每个变量做了一个 if 语句,并在数组中的值的索引处更改了值应该是省略.
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
// if the field was disabled then don't submit switch value
if (instagram) {
var i = values.switchGroup.indexOf("instagram");
values.switchGroup[i] = null
}
if (twitter) {
var i = values.switchGroup.indexOf("twitter");
values.switchGroup[i] = null
}
if (github) {
var i = values.switchGroup.indexOf("github");
values.switchGroup[i] = null
}
const data = new URLSearchParams(values);
const res = await axios
.post("/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>
我正在尝试 clear/reset 复选框禁用后的值。我最初认为我是通过使用 React 条件并将值设置为空字符串来实现此目的的,但如果复选框在被禁用之前已被激活,那么该值仍会被提交。这种行为似乎不正确,因为我的印象是未提交禁用的输入字段值?
React 条件表示如果表单被禁用,则复选框的值应该为空。
我正在使用 Formik 处理带有 Yup 模式验证的表单。
下面是我的表单的完整代码。
提前谢谢你。
import axios from "axios";
import * as Yup from "yup";
import Head from "next/head";
import Link from "next/link";
import Router from "next/router";
import { useState } from "react";
import Error from "../components/error";
import Layout from "../components/layout";
import Button from "react-bootstrap/Button";
import Spinner from "react-bootstrap/Spinner";
import { Formik, Form, Field, ErrorMessage } from "formik";
var instagram = false;
var twitter = false;
var github = false;
const validationSchema = Yup.object({
firstName: Yup.string()
.max(15, "Must be 15 characters or less"),
email: Yup.string().email("Invalid email address").required("Required"),
username: Yup.string()
.test(
'valid-instagram', "Instagram: may contain only alphanumeric characters, periods, and underscores", function (username){
var instagramRegex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/);
var instagramRes = instagramRegex.test(username)
if (instagramRes) { // if res is true then the username is valid and the switch can be enabled
instagram = false;
return true // return true to tell Yup the field is valid
} else {
instagram = true;
return true // true removes error message
}
}
)
.test(
'valid-twitter', "Twitter: may only contain alphanumeric characters or underscores", function (username){
var twitterRegex = new RegExp(/^[A-Za-z0-9_]{1,15}$/);
var twitterRes = twitterRegex.test(username)
if (twitterRes) { // if res is true then the username is valid and the switch can be enabled
twitter = false;
return true // return true to tell Yup the field is valid
} else {
twitter = true;
return true // true removes error message
}
}
)
.test(
'valid-github', "GitHub: may only contain alphanumeric characters or single hyphens", function (username){
var githubRegex = new RegExp(/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i);
var githubRes = githubRegex.test(username)
if (githubRes) { // if res is true then the username is valid and the switch can be enabled
github = false;
return true // return true to tell Yup the field is valid
} else {
github = true;
return true // true removes error message
}
}
)
.required("Required"),
acceptTerms: Yup.boolean()
.required("Required")
.oneOf([true], "You must accept the terms and conditions."),
switchGroup: Yup.array().required("At least one option must be selected"),
});
const initialValues = {
firstName: "",
email: "",
username: "",
acceptTerms: false, // added for our checkbox
switchGroup: [], // array for switches
};
export default function Signup() {
const [error, setError] = useState("");
return (
<Layout>
<Head>
<title>Signup - Notify.is</title>
</Head>
<div className="container-center">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
const data = new URLSearchParams(values);
const res = await axios
.post("http://localhost:8080/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>
{({ touched, errors, isSubmitting }) => (
<Form className="form">
<h1 className="display-4 pb-3">Get notified</h1>
<div className="form-label-group">
<Field
type="text"
name="firstName"
id="firstName"
placeholder="First name"
className={`form-control ${
touched.firstName && errors.firstName
? "is-invalid"
: null
}`}
/>
<label htmlFor="firstname">First name</label>
<small id="nameHelp" className="form-text text-muted">
Optional
</small>
</div>
<div className="form-label-group">
<Field
type="email"
name="email"
id="email"
placeholder="Email address"
className={`form-control ${
touched.email && errors.email ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="email"
className="invalid-feedback"
/>
<small id="emailHelp" className="form-text text-muted">
We'll never share your email with anyone else.
</small>
<label htmlFor="email">Email address</label>
</div>
<div className="form-label-group">
<Field
type="text"
name="username"
id="username"
autoCorrect="off"
autoCapitalize="none"
placeholder="Username"
className={`form-control ${
touched.username && errors.username ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="username"
className="invalid-feedback"
/>
<small id="usernameHelp" className="form-text text-muted">
The unavailable username you want.
</small>
<label htmlFor="username">Username</label>
</div>
<div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="instagram-switch"
value={instagram ? "" : "instagram"}
disabled={instagram}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="instagram-switch"
>
Instagram
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="twitter-switch"
value={twitter ? "" : "twitter"}
disabled={twitter}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="twitter-switch"
>
Twitter
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="github-switch"
value={github ? "" : "github"}
disabled={github}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="github-switch"
>
GitHub
</label>
<ErrorMessage
component="div"
name="switchGroup"
className="invalid-feedback"
/>
</div>
<small id="usernameHelp" className="form-text text-muted">
The service(s) we should check with.
</small>
</div>
<div className="custom-control custom-checkbox pt-3 mb-1">
<Field
type="checkbox"
name="acceptTerms"
id="acceptTerms"
className={`custom-control-input ${
touched.acceptTerms && errors.acceptTerms
? "is-invalid"
: null
}`}
/>
<label htmlFor="acceptTerms" className="custom-control-label">
By checking this box you agree to our:
</label>
<ErrorMessage
component="div"
name="acceptTerms"
className="invalid-feedback"
/>
</div>
<span className="grey termslabel">
<Link href="/tos">
<a className="terms" target="_blank">
Terms of Use
</a>
</Link>{" "}
and{" "}
<Link href="/privacy">
<a className="terms" target="_blank">
Privacy Policy
</a>
</Link>
</span>
<Button
className="btn-lg btn-primary btn-block mt-4"
variant="primary"
disabled={isSubmitting, error}
type="submit"
>
{isSubmitting && (
<Spinner
as="span"
animation="grow"
size="lg"
role="status"
aria-hidden="true"
/>
)}
{isSubmitting && <span> Submitting...</span>}
{!isSubmitting && <span>Sign up</span>}
</Button>
{error ? <Error error={error} /> : null}
<p className="mt-4 mb-3 text-muted text-center">
© Notify.is 2020
</p>
</Form>
)}
</Formik>
</div>
<style jsx>
{`
.display-4 {
font-weight: 700;
}
.terms {
text-decoration: underline;
}
.terms:hover {
text-decoration: none;
}
`}
</style>
</Layout>
);
}
检查 FieldArray 组件。它的渲染道具为来自 fieldArrays 的 adding/removing 值提供了一个 arrayHelper
。
我最终设法以不同于最初预期的方式完成了我想做的事情,但效果很好。
使用基于是否应禁用字段更改值的布尔变量,我为 Formik onSubmit prop 中的每个变量做了一个 if 语句,并在数组中的值的索引处更改了值应该是省略.
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
// if the field was disabled then don't submit switch value
if (instagram) {
var i = values.switchGroup.indexOf("instagram");
values.switchGroup[i] = null
}
if (twitter) {
var i = values.switchGroup.indexOf("twitter");
values.switchGroup[i] = null
}
if (github) {
var i = values.switchGroup.indexOf("github");
values.switchGroup[i] = null
}
const data = new URLSearchParams(values);
const res = await axios
.post("/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>