React Native中Yup结合Formik验证表单报firstname方法不存在错误
报错原因
yup.string().firstname is not a function报错的直接原因是Yup字符串类型的内置方法里不存在firstname这个API,你混淆了「字段名」和「校验规则」的概念。
认知纠正
Yup是通用的JavaScript对象校验库,并非仅支持邮箱、密码类字段校验。所有字符串、数字、布尔值、数组、对象类型的字段,都可以通过内置规则或者自定义规则实现校验。
你之前看到的.email()只是Yup为字符串类型预置的邮箱格式校验方法,和字段名无关,不管字段是firstname、lastname还是其他自定义名称,只要是字符串类型,都可以调用通用字符串校验规则。
普通文本字段常用校验规则
针对firstname、lastname这类普通文本字段,常用的内置校验方法如下:
.required(提示文案):标记字段为必填项,值为空时返回配置的错误提示.min(最小长度, 提示文案):限制字符串的最小字符数.max(最大长度, 提示文案):限制字符串的最大字符数,你原本想给firstname配置的20字符上限就用这个方法实现.matches(正则表达式, 提示文案):通过正则自定义格式规则,比如限制仅输入中英文、不允许特殊字符等.trim():自动去除字符串首尾空格,避免用户输入全空格绕过必填校验
代码修正说明
你的原有代码除了调用了不存在的firstname方法外,还有两个影响校验生效的问题:
- 定义的校验schema没有传入
useFormik的配置项中,Formik不会自动触发校验 - 手机号输入框的
handleChange绑定的字段名是number,和initialValues里定义的phonenumber字段名不匹配,会导致手机号字段的值无法同步到表单状态
修正后的核心代码如下:
// 完整表单校验规则 const contactValidationSchema = yup.object().shape({ firstname: yup .string() .max(20, "firstname must be 20 characters or less") .required("First Name is required"), lastname: yup .string() .max(20, "lastname must be 20 characters or less") .required("Last Name is required"), email: yup .string() .email("Please enter a valid email address") .required("Email is required"), phonenumber: yup .string() .matches(/^[0-9\-+]{7,15}$/, "Please enter a valid phone number") .required("Phone number is required"), message: yup .string() .min(10, "Message must be at least 10 characters long") .required("Message content cannot be empty") }) const ContactUs = () => { // 补充errors、touched、handleBlur用于错误提示展示 const { handleChange, handleSubmit, values, errors, touched, handleBlur } = useFormik({ initialValues: { email: '', message: '', phonenumber: '', firstname: '', lastname: '' }, validationSchema: contactValidationSchema, // 必须传入校验规则才会生效 onSubmit: values => { alert("Your message is submitted") } }) return ( <SafeAreaView> <KeyboardAvoidingView behavior="position" keyboardVerticalOffset = {30} > <TouchableWithoutFeedback onPress= {() => Keyboard.dismiss()}> <View > <View style={styles.title}> <Header title={"Send Your Message"} style = {styles.title} /> </View> <View> <Input placeholder='First Name' autoCapitalize='none' autoCompleteType='name' keyboardType='default' autoCorrect = {true} onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')} /> {/* 可在此处加错误提示:{touched.firstname && errors.firstname && <Text style={styles.errorText}>{errors.firstname}</Text>} */} <Input placeholder='Last Name' autoCapitalize='none' autoCompleteType='name' keyboardType='default' autoCorrect = {true} onChangeText={handleChange('lastname')} onBlur={handleBlur('lastname')} /> <Input placeholder='Email' autoCapitalize='none' autoCompleteType='email' keyboardType='email-address' autoCorrect={true} onChangeText={handleChange('email')} onBlur={handleBlur('email')} /> <Input placeholder= 'Phone Number' autoCapitalize='none' autoCompleteType='number' keyboardType='phone-pad' autoCorrect= {true} // 修正字段名不匹配问题 onChangeText={handleChange('phonenumber')} onBlur={handleBlur('phonenumber')} /> <Input placeholder='Message' style = {styles.input} autoCapitalize='none' keyboardType='default' autoCorrect = {true} onChangeText={handleChange('message')} onBlur={handleBlur('message')} /> </View> <Button onPress= {handleSubmit}>Submit</Button> </View> </TouchableWithoutFeedback> </KeyboardAvoidingView> </SafeAreaView> ) }
提示:如果需要展示校验错误,建议结合
touched标记判断,只有用户聚焦过又离开的字段才展示错误,避免页面刚加载就弹出一堆报错影响体验。
内容的提问来源于stack exchange,提问作者shutu
相关产品推荐
相关产品推荐

