防止多步 Formik 表单在重新渲染上一步时重置表单控件输入
Posted
技术标签:
【中文标题】防止多步 Formik 表单在重新渲染上一步时重置表单控件输入【英文标题】:Prevent a multi step Formik form from resetting the form control inputs on re-rendering of the previous step 【发布时间】:2021-07-22 07:18:39 【问题描述】:我正在尝试使用 formik 库在 nextjs 中实现多步表单。一切似乎都很好,除非用户单击后退按钮表单由于状态更改而被重置。有没有什么方法可以实现表单中所有步骤的重新渲染,而不需要从输入字段中清除数据?我希望在用户点击表单最后一步的提交按钮时重置表单。
这是我的渲染代码:
import QuoteStep1 from '../components/QuoteStep1'
import QuoteStep2 from '../components/QuoteStep2'
import QuoteStep3 from '../components/QuoteStep3'
import quoteProgressStyles from '../styles/QuoteProgress.module.css'
import useContext from 'react'
import QuoteContext from '../contexts/QuoteContext'
const quote = () =>
const render, data = useContext(QuoteContext)
const [step, setStep] = render
const [formValues, setFormValues] = data
return (
<div className=quoteProgressStyles.section>
<div className=quoteProgressStyles.container>
<div className=quoteProgressStyles.progressBar>
<div className=`$quoteProgressStyles.step $step === 1 || step === 2 || step === 3 ? `$quoteProgressStyles.active` : null` ><b>Step1</b>Requirement Information</div>
<div className=`$quoteProgressStyles.step $step === 2 || step === 3 ? `$quoteProgressStyles.active` : null` ><b>Step2</b>Personal Information</div>
<div className=`$quoteProgressStyles.step $step === 3 ? `$quoteProgressStyles.active` : null` ><b>Step3</b>Delivery Information</div>
</div>
<div>
step === 1 ? <QuoteStep1 /> : null
step === 2 ? <QuoteStep2 /> : null
step === 3 ? <QuoteStep3 /> : null
</div>
</div>
</div>
)
export default quote
这是第一步:
import Formik, Form, useField from 'formik'
import * as Yup from 'yup'
import QuoteStep1Styles from '../styles/QuoteStep1.module.css'
import useContext from 'react'
import QuoteContext from '../contexts/QuoteContext'
import MaskedInput from 'react-input-mask';
import useEfeect from 'react'
const QuoteStep1 = () =>
const render, data = useContext(QuoteContext)
const [step, setStep] = render
const [formValues, setFormValues] = data
const MyMaskedTextInput = ( label, ...props ) =>
const [field, meta] = useField(props)
return (
<div className=QuoteStep1Styles.outerBox>
<label htmlFor=props.id || props.name>label</label>
<div className=QuoteStep1Styles.innerBox>
<MaskedInput ...field ...props />
<label htmlFor=props.id || props.name>Units</label>
</div>
</div>
)
return (
<div>
<Formik
initialValues=formValues
onSubmit=(values, setSubmitting ) =>
setTimeout(() =>
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
, 400)
setStep(2)
>
<Form className=QuoteStep1Styles.form>
<div className=QuoteStep1Styles.SPR>
<MyMaskedTextInput
label="SPR"
name="SPR"
mask="9999"
maskChar=" "
/>
</div>
<div className=QuoteStep1Styles.DFR>
<MyMaskedTextInput
label="DFR"
name="DFR"
mask="9999"
maskChar=" "
/>
</div>
<div className=QuoteStep1Styles.ACR>
<MyMaskedTextInput
label="ACR"
name="ACR"
mask="9999"
maskChar=" "
/>
</div>
<div className=QuoteStep1Styles.HWS>
<MyMaskedTextInput
label="HWS"
name="HWS"
mask="9999"
maskChar=" "
/>
</div>
<button className=QuoteStep1Styles.button type="submit">CONTINUE</button>
</Form>
</Formik>
</div>
)
export default QuoteStep1
这是第 2 步:
import Formik, Form, useField from 'formik'
import * as Yup from 'yup'
import MaskedInput from 'react-input-mask';
import QuoteStep2Styles from '../styles/QuoteStep2.module.css'
import useContext from 'react'
import QuoteContext from '../contexts/QuoteContext'
const QuoteStep2 = () =>
const render, data = useContext(QuoteContext)
const [step, setStep] = render
const [formValues, setFormValues] = data
const MyTextInput = ( label, ...props ) =>
const [field, meta] = useField(props)
return (
<div className=QuoteStep2Styles.outerBox>
<label className=QuoteStep2Styles.label htmlFor=props.id || props.name>label</label>
<div className=QuoteStep2Styles.innerBox>
<input className=QuoteStep2Styles.input ...field ...props />
meta.touched && meta.error ? (
<div className=QuoteStep2Styles.error>meta.error</div>
) : null
</div>
</div>
)
const MyMaskedTextInput = ( label, ...props ) =>
const [field, meta] = useField(props)
return (
<div className=QuoteStep2Styles.outerBox>
<label className=QuoteStep2Styles.label htmlFor=props.id || props.name>label</label>
<div className=QuoteStep2Styles.innerBox>
<MaskedInput className=QuoteStep2Styles.input ...field ...props />
meta.touched && meta.error ? (
<div className=QuoteStep2Styles.error>meta.error</div>
) : null
</div>
</div>
)
return (
<div>
<Formik
initialValues=formValues
validationSchema=Yup.object(
fName: Yup.string()
.max(50, 'Must be 50 characters or less')
.required('Required'),
lName: Yup.string()
.max(50, 'Must be 50 characters or less')
.required('Required'),
cName: Yup.string()
.max(120, 'Must be 120 characters or less'),
email: Yup.string()
.email('Invalid email address')
.required('Required'),
phone: Yup.string()
.required('Required')
)
onSubmit=(values, setSubmitting ) =>
setTimeout(() =>
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
, 400)
setStep(3)
>
<div className=QuoteStep2Styles.section>
<div className=QuoteStep2Styles.container>
<Form className=QuoteStep2Styles.form>
<div className=QuoteStep2Styles.fName>
<MyTextInput
label="First Name"
name="fName"
type="text"
maxLength='50'
autoComplete="given-name"
placeholder="Jane"
/>
</div>
<div className=QuoteStep2Styles.lName>
<MyTextInput
label="Last Name"
name="lName"
type="text"
maxLength='50'
autoComplete="family-name"
placeholder="Doe"
/>
</div>
<div className=QuoteStep2Styles.cName>
<MyTextInput
label="Company Name"
name="cName"
type="text"
maxLength='120'
autoComplete="organization"
placeholder="Acme Widget, Inc"
/>
</div>
<div className=QuoteStep2Styles.email>
<MyTextInput
label="Email Address"
name="email"
type="email"
autoComplete="email"
placeholder="jane@email.com"
/>
</div>
<div className=QuoteStep2Styles.phone>
<MyMaskedTextInput
label="Phone"
name="phone"
mask="(999) 999-9999"
autoComplete="tel-national"
placeholder="(000) 000-0000"
/>
</div>
<div className=`$QuoteStep2Styles.outerBox $QuoteStep2Styles.buttons`>
<button type="submit">CONTINUE</button>
<button onClick=() =>setStep(1)>BACK</button>
</div>
</Form>
</div>
</div>
</Formik>
</div>
)
export default QuoteStep2
【问题讨论】:
【参考方案1】:您可以在 formik 对象中设置 enableReinitialize 属性
示例: enableReinitialize: true,
文档链接 https://formik.org/docs/api/withFormik#enablereinitialize-boolean
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于防止多步 Formik 表单在重新渲染上一步时重置表单控件输入的主要内容,如果未能解决你的问题,请参考以下文章