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

Formik搭配react-native-dropdown-picker提交报TypeError如何解决?

报错原因

该TypeError的触发原因非常明确:你错误地从Formik自动注入的field子对象中读取了不存在的open属性,核心问题有两点:

  • Formik为表单控件生成的field对象默认仅包含name、value、onChange、onBlur四个和表单值绑定的核心属性,open、setOpen、items、setItems属于DropdownPicker自身的UI状态,不属于Formik管理的范畴,不会被注入到field对象中
  • 你调用Dropdown组件时传入的open等配置是挂载在顶层props上的,不会被合并到field子对象中,从field中解构这些属性必然返回undefined,访问时就触发了报错。

你写的CustomInput没有报错,就是因为它仅从field中读取了Formik默认提供的四个属性,没有额外访问不存在的字段。

修复方案

你只需要调整Dropdown组件的属性解构逻辑,把不属于Formik field的属性移到顶层props中读取即可:

第一步:修改Dropdown组件的属性解构

const DropDown = (props) => {
  const {
    // 仅从field中读取Formik注入的表单相关属性
    field: { name, value, onBlur },
    form: { errors, touched, setFieldTouched, setFieldValue },
    // Dropdown自身的UI状态从顶层props读取
    open,
    items,
    setOpen,
    setValue,
    setItems,
    placeholder,
    style,
    dropDownMaxHeight,
    ...inputProps
  } = { ...props };
  const hasError = errors[name] && touched[name];

  // 新增选中值同步逻辑,把Dropdown的选中值同步到Formik
  const handleChangeValue = (callback) => {
    callback((selectedVal) => {
      setFieldValue(name, selectedVal);
      return selectedVal;
    })
  }

  return (
    <View>
      <DropDownPicker
        open={open}
        value={value}
        name={name}
        items={items}
        onBlur={() => {
          setFieldTouched(name);
          onBlur(name);
        }}
        setOpen={setOpen}
        // 替换原来的setValue为带同步逻辑的方法
        setValue={handleChangeValue}
        setItems={setItems}
        placeholder={placeholder}
        containerStyle={styles.height}
        style={[styles.color, hasError && styles.errorInput, { ...style }]}
        itemStyle={styles.item}
        dropDownStyle={styles.color}
        dropDownMaxHeight={dropDownMaxHeight}
        {...inputProps}
      />
      {hasError && <Text style={styles.errorText}>{errors[name]}</Text>}
    </View>
  );
};

第二步:父组件调用时正常传递Dropdown相关状态即可

// 父组件自行维护Dropdown的UI状态
const [renewalOpen, setRenewalOpen] = useState(false);
const [renewalItems, setRenewalItems] = useState([
  {label: '月付', value: 'month'},
  {label: '季付', value: 'quarter'},
  {label: '年付', value: 'year'}
]);

// 渲染Field组件时直接传入状态即可
<Field
  name="renewal"
  component={DropDown}
  open={renewalOpen}
  setOpen={setRenewalOpen}
  items={renewalItems}
  setItems={setRenewalItems}
  placeholder="请选择续费周期"
/>

内容的提问来源于stack exchange,提问作者AsZik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 11:00:05