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

Formik内嵌Table时,设置输入框初始值后无法修改的问题求助

解决Formik表格内输入框无法修改的思路

核心问题根源

你直接将typeClient.label硬赋值给<Field>的value,等于绕过了Formik的状态管理机制——每次输入时,Formik会优先读取你硬设的初始值,导致输入内容被强制回滚。必须把列表数据完全纳入Formik的initialValues,通过name属性绑定状态,才能让输入框正常响应修改。

具体解决步骤

  1. 把列表数据映射到initialValues
    将你的typeClients数组转换为Formik可管理的结构,比如新增一个数组字段clientTypes,每个元素对应原列表的属性:

    const initialValues = {
      clientTypes: typeClients.map(item => ({
        label: item.label,
        id: item.id // 保留原数据标识,方便后续提交对应
      }))
    };
    
  2. 通过索引绑定Field的name属性
    遍历Formik维护的values.clientTypes,给每个<Field>设置带索引的name路径,让Formik能精准追踪每行的状态:

    <Field name={`clientTypes[${index}].label`} type="text" />
    

    注意:不要手动设置value属性,Formik会自动通过name关联initialValues和当前状态。

  3. 维护行级编辑状态
    用React的useState管理每行的编辑开关,比如:

    const [isEditing, setIsEditing] = useState(Array(typeClients.length).fill(false));
    const toggleEdit = (index) => {
      const newState = [...isEditing];
      newState[index] = !newState[index];
      setIsEditing(newState);
    };
    

    点击"Update"时切换对应行的isEditing状态,决定显示<Field>还是普通文本。

完整示例代码片段

import { Formik, Form, Field } from 'formik';
import { useState } from 'react';

// 假设你的原始列表数据
const typeClients = [
  { id: 1, label: 'Client Type 1' },
  { id: 2, label: 'Client Type 2' }
];

const ClientTable = () => {
  const [isEditing, setIsEditing] = useState(Array(typeClients.length).fill(false));
  const toggleEdit = (index) => {
    const newState = [...isEditing];
    newState[index] = !newState[index];
    setIsEditing(newState);
  };

  return (
    <Formik
      initialValues={{
        clientTypes: typeClients.map(item => ({ label: item.label, id: item.id }))
      }}
      onSubmit={(values) => {
        // 提交时直接获取修改后的数组
        console.log('Updated data:', values.clientTypes);
      }}
    >
      {({ values }) => (
        <Form>
          <table border="1">
            <thead>
              <tr>
                <th>Client Type</th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody>
              {values.clientTypes.map((type, index) => (
                <tr key={type.id}>
                  <td>
                    {isEditing[index] ? (
                      <Field name={`clientTypes[${index}].label`} type="text" />
                    ) : (
                      type.label
                    )}
                  </td>
                  <td>
                    <button type="button" onClick={() => toggleEdit(index)}>
                      {isEditing[index] ? 'Save' : 'Update'}
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
          <button type="submit" style={{ marginTop: '10px' }}>
            Submit All Changes
          </button>
        </Form>
      )}
    </Formik>
  );
};

export default ClientTable;

关键注意事项

  • 始终基于Formik的values渲染表格内容,而非原始的typeClients数组,确保显示的是最新修改状态。
  • 保留原数据的唯一标识(如id),避免用数组索引作为key(数据顺序变化时会导致渲染异常)。
  • 若需要单独保存单行数据,可在点击"Save"时调用Formik的setFieldValue方法更新对应字段,再切换编辑状态。

内容的提问来源于stack exchange,提问作者Jean François Manatane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:17:38