React预填充表单输入框如何添加校验?提交空值报undefined如何解决
你代码里的校验逻辑存在几个核心错误,调整后就能正常运行:
- 混淆了
undefined原始值和字符串'undefined',你所有判断里写的!== 'undefined'是对比字符串,而清空输入后拿到的是undefined类型的值,判断自然不生效 valid函数没有返回布尔值,导致提交时if (valid())的判断永远为假,后续提交逻辑不会执行- 直接修改原state中的data对象,属于可变数据更新,会导致React状态更新异常
- 只做了非undefined判断,没处理用户输入为空字符串的场景,也没加手机号格式校验
修改后的完整代码
const EditContact = inject('Contacts')(observer((props) => { const { text, Contactfirst, apptContacts } = props; const { updateContact } = apptContacts; const CMS = text.appointmentManager.editAppointmentContact; const [state, setState] = React.useState({ data: { // 初始化时给后端返回值兜底,避免初始为undefined firstName: Contactfirst[0] ?? '', lastName: Contactfirst[1] ?? '', number: Contactfirst[2] ?? '', }, firstNameValid: '', lastNameValid: '', numberValid: '', }); const handleTextareaChange = (event) => { const { name, value } = event.target; // 采用不可变方式更新状态,不直接修改原state对象 setState(prev => ({ ...prev, data: { ...prev.data, [name]: value } })); }; const valid = () => { let isValid = true; const errors = { firstNameValid: '', lastNameValid: '', numberValid: '' }; // 名字必填校验 if (!state.data.firstName.trim()) { errors.firstNameValid = 'Required.Please enter your given name.'; isValid = false; } // 姓氏必填校验 if (!state.data.lastName.trim()) { errors.lastNameValid = 'Required.Please enter your family name.'; isValid = false; } // 手机号校验,可根据实际业务调整正则规则 const phoneReg = /^1[3-9]\d{9}$/; if (!state.data.number.trim()) { errors.numberValid = 'Required.Please enter your mobile number.'; isValid = false; } else if (!phoneReg.test(state.data.number.trim())) { errors.numberValid = 'Please enter a valid mobile number.'; isValid = false; } setState(prev => ({ ...prev, ...errors })); return isValid; }; const saveButton = () => { if (valid()) { const personName = `${state.data.firstName} ${state.data.lastName}`; const primaryContact = { name: personName, phoneNumber: state.data.number, }; // 此处补充你的提交逻辑,比如调用updateContact接口 } }; return ( <div> <VerticalSpacing size={ABLE_SPACING_SIZE.spacing4x} /> <h1 tabIndex="-1" className="HeadingB mt-sheet-heading"> {CMS.heading1} </h1> <VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} /> <TextField id="givenName" name="firstName" label={CMS.name} onChange={handleTextareaChange} value={state.data.firstName} /> <p>{state.firstNameValid}</p> <VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} /> <TextField id="familyName" name="lastName" label={CMS.familyName} onChange={handleTextareaChange} value={state.data.lastName} /> <p>{state.lastNameValid}</p> <VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} /> <TextField id="mobileNumber" name="number" label={CMS.mobile} onChange={handleTextareaChange} value={state.data.number} /> <p>{state.numberValid}</p> <VerticalSpacing size={ABLE_SPACING_SIZE.spacing4x} /> <ActionButton className={styles.saveCta} variant="HighEmphasis" label={CMS.saveCTA} onClick={() => saveButton()} /> </div> ); })); export default EditContact ;
关键改动说明
- 初始化状态时用空值合并运算符
??给后端返回值做兜底,避免初始值为undefined - 输入框的change事件改为不可变方式更新状态,保证React能正常触发重渲染
- 重写了校验逻辑,分别对三个字段做必填校验,手机号额外增加了格式校验,校验不通过时设置对应错误提示,校验通过返回true
- 简化了输入框的value属性,因为初始化已经做了兜底,不需要再额外判断undefined
- 校验函数新增了布尔值返回,提交逻辑只有在校验全部通过后才会执行
内容的提问来源于stack exchange,提问作者Milan Sai
相关产品推荐
相关产品推荐

