使用Formik限制react-phone-number-input输入长度时输入框仍更新的问题
问题:react-phone-number-input与Formik集成时输入长度限制失效
我在项目中集成了react-phone-number-input和Formik库,希望将手机号输入长度限制为18位。以下是我使用的逻辑:
<PhoneNumberInput id="patient.phone.number" values={number} errors={phoneNumberError} touched={phoneNumberTouched} onBlur={handleBlur} onChange={(num: string | null) => phoneNumberHandler(num)} placeholder={t('profile.phone')} label={t('profile.phone')} /> const phoneNumberHandler = (num: string | null) => { if (num && num.length >= 18) return; if (num && num.length < 18) { console.log('num', num); const phoneNumber = parsePhoneNumber(num); console.log('phoneNumber', phoneNumber); if (phoneNumber) { formik.setValues({ ...formik.values, patient: { ...formik.values.patient, phone: { number: phoneNumber.number, region: phoneNumber?.country || '', countryCode: phoneNumber?.countryCallingCode || '', }, }, }); } } };
奇怪的是,当num.length>=18时,console.log('num')、console.log('phoneNumber')以及Formik的values都不再更新,从这一角度看代码似乎正常,但不知为何屏幕上的手机号输入框内容却一直在更新,不受num.length的影响。请问我的代码哪里存在错误?
问题原因
你只在phoneNumberHandler里拦截了Formik的值更新,但react-phone-number-input组件自身的内部状态并没有被限制。组件会独立维护输入框的显示内容,当你在输入长度达标后直接return,没有将最新的输入值同步回组件的受控状态,导致组件内部状态继续更新,而Formik的值停留在17位,最终出现显示内容和实际存储值不一致的情况。
另外你代码里的PhoneNumberInput属性写错了,应该是value={number}而非values={number},这也是组件状态不受控的诱因之一。
解决方法
让PhoneNumberInput成为完全受控组件,确保组件显示值始终和Formik的values保持一致,同时主动截断超过18位的输入内容:
<PhoneNumberInput id="patient.phone.number" value={number} // 修正属性名 errors={phoneNumberError} touched={phoneNumberTouched} onBlur={handleBlur} onChange={(num: string | null) => phoneNumberHandler(num)} placeholder={t('profile.phone')} label={t('profile.phone')} /> const phoneNumberHandler = (num: string | null) => { if (!num) { formik.setValues({ ...formik.values, patient: { ...formik.values.patient, phone: { ...formik.values.patient.phone, number: '', }, }, }); return; } // 先截断到18位以内 const truncatedNum = num.slice(0, 18); const phoneNumber = parsePhoneNumber(truncatedNum); if (phoneNumber) { formik.setValues({ ...formik.values, patient: { ...formik.values.patient, phone: { number: phoneNumber.number, region: phoneNumber?.country || '', countryCode: phoneNumber?.countryCallingCode || '', }, }, }); } };
关键说明
- 不要在输入超长度时直接
return,而是主动截断内容并同步到Formik,这样组件的显示值会和Formik的值强制保持一致 - 必须确保组件的
value属性绑定到Formik的存储值,让组件完全受控于外部状态
内容的提问来源于stack exchange,提问作者marcinb1986
相关产品推荐
相关产品推荐

