React+Formik注册表单Submit按钮点击无法提交问题修复
Formik注册表单提交无响应修复方案
核心问题根因
- 所有表单输入控件未接入Formik状态管理:自定义的
FormikControl仅渲染原生input,没有绑定Formik的字段状态,用户输入内容不会同步到Formik的values对象,必填字段始终为空,校验永远不通过 - 提交按钮禁用逻辑缺陷:按钮绑定了
disabled={!formik.isValid},由于初始状态下表单校验未触发+字段值未同步,按钮始终处于禁用状态,点击自然无法触发提交 - 单选框实现完全错误:手写的原生radio没有绑定
name="modeOfContact"属性,value值也和校验规则要求的emailmoc/telephonemoc不匹配,Formik无法获取该必填字段的值 - 多处拼写错误:options配置项里的
vlaue为拼写错误,FormikContainer里的校验属性validationschema不符合Formik要求的驼峰命名validationSchema - 校验规则写法错误:
confirmPassword的oneOf校验把空字符串放进了匹配数组,会导致两次密码不一致也能通过校验
分步修复代码
1. 重构FormikControl组件,接入Formik字段绑定
修改FormikControl.js,用Formik内置的Field组件替换原生input,新增radio类型控件支持:
import React from 'react'; import { Field } from 'formik'; function FormikControl({ control, id, label, name, options, ...rest }) { return ( <> {control === 'input' && ( <> <label htmlFor={id || name}>{label}</label> <Field id={id || name} name={name} {...rest} /> </> )} {control === 'radio' && ( <div style={{margin: '12px 0'}}> <label style={{fontWeight: 'bold', display: 'block', marginBottom: '8px'}}>{label}</label> {options.map(opt => ( <label key={opt.value} style={{marginRight: '20px', fontWeight: 'normal'}}> <Field type="radio" name={name} value={opt.value} style={{marginRight: '6px'}} /> {opt.key} </label> ))} </div> )} </> ); } export default FormikControl;
2. 修正RegistrationForm.js的错误
替换原生radio控件、修正拼写错误、调整校验规则和按钮禁用逻辑:
import React from 'react'; import { Formik, Form } from 'formik'; import * as yup from 'yup'; import FormikControl from './FormikControl'; import classes from './Registration.module.css'; function Registrationform() { // 修正value拼写错误 const options = [ { key: 'Email', value: 'emailmoc' }, { key: 'Telephone', value: 'telephonemoc' } ]; const initialValues = { email: '', password: '', confirmPassword: '', modeOfContact: '', phone: '' }; const validationSchema = yup.object({ email: yup.string().email('Invalid email format').required('Required'), password: yup.string().required('Required'), // 修正oneOf参数,移除数组内的空字符串 confirmPassword: yup .string() .oneOf([yup.ref('password')], 'Passwords must match') .required('required'), modeOfContact: yup.string().required('Required'), phone: yup.string().when('modeOfContact', { is: 'telephonemoc', then: yup.string().required('Required') }) }); const onSubmit = (values) => { console.log('Form data', values); }; return ( <div> <h1>Registration</h1> <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={onSubmit} validateOnMount={true} > {(formik) => { return ( <Form className={classes.Registrationform}> <FormikControl control="input" type="email" label="Email" name="email" /> <FormikControl control="input" type="password" label="Password" name="password" /> <FormikControl control="input" type="password" label="Confirm Password" name="confirmPassword" /> <FormikControl control="input" type="text" label="Phone number" name="phone" /> {/* 替换手写radio为封装的控件 */} <FormikControl control="radio" label="Mode of Contact" name="modeOfContact" options={options} /> {/* 修正禁用逻辑:表单已修改且校验通过时才可点击 */} <button type="submit" disabled={!(formik.dirty && formik.isValid)}> Submit </button> </Form> ); }} </Formik> </div> ); } export default Registrationform;
3. 修正FormikContainer.js的属性拼写错误
避免其他表单出现同类问题,把错误的属性名validationschema改成Formik要求的validationSchema:
<Formik initialValues={initialValues} validationSchema={validationschema} onSubmit={onSubmit} >
验证结果
修改完成后,表单输入内容、选择联系方式后提交按钮会自动变为可点击状态,点击按钮即可正常触发onSubmit逻辑,控制台会打印完整的表单数据。
内容的提问来源于stack exchange,提问作者Lizzy
相关产品推荐
相关产品推荐

