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

ReactJS Formik动态食谱步骤输入值提交未捕获,求解决方案

问题:Formik提交时无法捕获烹饪步骤输入值

我正在构建一个食谱数据库,实现了点击“添加步骤”新增输入框、“删除最后一步”移除输入框的功能——输入框能正常显示和输入内容,但通过Formik提交表单时,步骤输入的信息完全没被捕获到。

现有代码片段

步骤输入区域代码:

<h4>Instructions</h4>
{Array.from(Array(step)).map((c, index) => {
  const stepNumber = index + 1;
  return (
    <Field
      type="text"
      name={`instructions[${index}]`}
      placeholder={`Instructions step ${stepNumber}`}
      component={Input}
      onChange={e => setIngredients(e.target.value)}
    />
  );
})}
<ButtonWrapper>
  <Button
    recipe
    type="button"
    onClick={() => handleInstructionRemove()}
    contain
  >
    Remove Last Instruction
  </Button>
  <Button
    color="green"
    contain
    type="button"
    onClick={() => setStep(step + 1)}
  >
    Add Step
  </Button>
</ButtonWrapper>

状态管理与Formik配置:

const [step, setStep] = useState(1);
<Formik
  initialValues={{
    title: "",
    author: "",
    ingredients: [],
    amount: [],
    size: [],
    temperature: "",
    degrees: "f",
    instructions: [],
    cookingTime: "",
    description: "",
    serving: "",
    category: "main",
    image: null
  }}
  validationSchema={RecipeSchema}
  onSubmit={async (values) => {
    try {
      const url = await handleUpload();
      createRecipe(values, url);
      console.log(values);
    } catch (err) {
      console.log(err);
    }
  }}
>

问题原因

  1. 自定义onChange覆盖Formik逻辑:给Field组件加了自定义的onChange,错误调用setIngredients的同时,完全跳过了Formik默认的字段值同步流程,导致输入值根本没进到Formik的values里。
  2. 步骤数量与Formik数组不同步:删除步骤时只更新了本地step状态,没同步缩短Formik的instructions数组,可能导致长度不匹配。

修复方案

1. 移除Field的自定义onChange

Formik的Field组件会自动根据name属性(这里的instructions[${index}])把输入值同步到对应的数组位置,不需要手动写onChange:

<h4>Instructions</h4>
{Array.from(Array(step)).map((c, index) => {
  const stepNumber = index + 1;
  return (
    <Field
      type="text"
      name={`instructions[${index}]`}
      placeholder={`Instructions step ${stepNumber}`}
      component={Input}
      // 删掉自定义onChange行
    />
  );
})}

2. 同步删除步骤时的Formik数组

修改handleInstructionRemove,同时更新本地step状态和Formik的instructions数组(需通过Formik的render props或useFormik钩子获取setValues方法):

// 假设在Formik的children组件内,通过props拿到setValues
const handleInstructionRemove = () => {
  if (step <= 1) return;
  // 更新本地步骤数量
  setStep(prev => prev - 1);
  // 同步缩短Formik的instructions数组
  setValues(prevValues => ({
    ...prevValues,
    instructions: prevValues.instructions.slice(0, -1)
  }));
};

3. 初始化时保持状态与Formik数组一致

确保本地step初始值和Formik初始的instructions数组长度匹配:

// 从Formik的initialValues里取长度,无值则默认1
const [step, setStep] = useState(initialValues.instructions.length || 1);

额外说明

Formik已经帮你管理了表单所有字段的状态,包括数组类型的instructions,你只需要用step控制输入框的渲染数量即可,不需要额外用useState存储每个步骤的输入值。添加步骤时,Formik会自动在instructions数组中新增对应位置的内容,提交时就能完整捕获所有步骤的输入了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:15:35