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

Formik动态表单初始值无法读取,表单无法回显数据求助

Formik动态表单初始值无法回显问题解决

问题情况

使用Formik构建动态表单,初始值由generateInitialValues函数生成:无数据时返回空结构对象,存在历史数据时返回填充数据的同结构对象。但表单无法回显已有数据,测试发现:

  • 打印formik.values能看到带值的对象,字段的key也正确
  • 通过formik.values['Ticket' + formNumber + '.Field' + data.ticketDetailForm[i].id]读取时返回undefined
  • 手动输入字段内容后,Formik更新值,此时能正常读取对应值
  • 已设置enableReinitialize: true,表单提交可正常保存数据,仅初始值读取有问题

问题根源

  1. 初始值key与表单字段key不匹配:生成空初始值时,Field的key用了循环索引j+1,但表单字段的key用的是data.ticketDetailForm[i].id,如果id不是连续的1、2、3,会导致两者key不对应。
  2. 嵌套对象访问方式错误:初始值是嵌套结构({ Ticket1: { FieldX: "" } }),但代码中用扁平的点连接字符串(如"Ticket1.FieldX")作为key访问formik.values,而Formik的嵌套结构需要用formik.values.Ticket1.FieldX或formik.values["Ticket1"]["FieldX"]的方式访问。

修复方案

1. 修正初始值生成逻辑

将generateInitialValues中Field的key从j+1改为data.ticketDetailForm[j].id,确保和表单字段的key完全对应:

function generateInitialValues(formData) {
  if(!formData.ticketDetails){
    let object = {};    
    for (let i = 0; i < nrOfTickets; i++){
      object["Ticket" + (i+1)] = {};
      for (let j = 0; j < data.ticketDetailForm.length; j++){
        // 用data.ticketDetailForm[j].id作为Field的key,而非循环索引
        object["Ticket" + (i+1)]["Field" + data.ticketDetailForm[j].id] = "";
      }
    }
    return object;
  } else {
    return formData.ticketDetails;
  }
}

2. 修正formik.values的访问方式

在GenerateFields中,将扁平key访问改为嵌套对象访问,同时添加可选链避免对象不存在时抛出错误:

// 原错误写法
formik.values['Ticket' + formNumber + '.Field' + data.ticketDetailForm[i].id]

// 修正为嵌套访问
formik.values['Ticket' + formNumber]?.['Field' + data.ticketDetailForm[i].id]

3. 确保字段name的正确性

表单input的name属性保持不变("Ticket" + formNumber + ".Field" + data.ticketDetailForm[i].id),Formik会自动将点分隔的name解析为嵌套路径,匹配初始值的结构。

完整修正代码

export default function TicketDetails({formData, editFormData}) {
  
  const initialObject = generateInitialValues(formData);

  const formik = useFormik({
    enableReinitialize: true,
    initialValues: initialObject,
    onSubmit: values => {
      editFormData({ticketDetails: values});
    },
  });

  return (
    <form id="ticketDetails" onSubmit={formik.handleSubmit}>
      <GenerateCards formik={formik} />
      <div className='h-6'></div>
    </form>
  );
}

function GenerateCards({formik}){
  let output = [];
  for (let i = 0; i < nrOfTickets; i++){
    output.push(
    <div key={i} className="divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow mt-6">
      <div className="px-4 py-5 sm:px-6">
        <h3 className="text-lg font-semibold leading-6 text-gray-900">Ticket #{i+1}</h3>
      </div>
      <div className="px-4 py-5 sm:p-6 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2 lg:gap-4">
        <GenerateFields formNumber={i+1} formik={formik}/>
      </div>
    </div>
    );
  };
  return output;
}

function GenerateFields({formNumber, formik}) {
  let fields = [];
  for (let i = 0; i < data.ticketDetailForm.length; i++){
    const ticketKey = `Ticket${formNumber}`;
    const fieldKey = `Field${data.ticketDetailForm[i].id}`;
    const fieldValue = formik.values[ticketKey]?.[fieldKey];

    console.log(formik.values);
    console.log(`${ticketKey}.${fieldKey}`);
    console.log(fieldValue);

    fields.push(
      <div key={i}>
      <label className="block text-sm font-medium leading-6 text-gray-900 pl-0.5 pb-1">{data.ticketDetailForm[i].label}</label>
      <input
        name={`${ticketKey}.${fieldKey}`}
        value={fieldValue || ""}
        onChange={formik.handleChange}
        type={data.ticketDetailForm[i].type}
        className="mb-4 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
        placeholder={data.ticketDetailForm[i].placeholder}
      />
      </div>
    );
  }
  return fields;
}

function generateInitialValues(formData) {
  if(!formData.ticketDetails){
    let object = {};    
    for (let i = 0; i < nrOfTickets; i++){
      const ticketKey = `Ticket${i+1}`;
      object[ticketKey] = {};
      for (let j = 0; j < data.ticketDetailForm.length; j++){
        const fieldKey = `Field${data.ticketDetailForm[j].id}`;
        object[ticketKey][fieldKey] = "";
      }
    }
    return object;
  } else {
    return formData.ticketDetails;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:15:19