You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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方法外,还有两个影响校验生效的问题:

  1. 定义的校验schema没有传入useFormik的配置项中,Formik不会自动触发校验
  2. 手机号输入框的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 11:03:14