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

Formik FieldArray中TextField输入单字符即失焦问题排查

问题原因

输入单字符就失焦的核心原因是每次输入触发表单状态更新、组件重渲染时,React判定输入框对应的DOM节点被销毁重建,焦点自然丢失。你配置key的方式存在明显错误,是触发这个问题的直接诱因:

  • 错误使用数组下标index作为列表项key:从FieldArray判断你用的是Formik表单库,输入时表单状态更新会生成新的状态引用,用下标作为key时,React的diff算法无法稳定匹配上一次渲染的对应输入框节点,会直接销毁旧节点创建新节点。
  • 冗余key配置干扰diff逻辑:你在多层嵌套的Grid组件、甚至包裹整个列表的容器div上都加了key属性,尤其是外层容器的key={myIndex},一旦传入的myIndex或相关引用变动,整个列表容器会被直接卸载重建,所有输入框都会失焦。内层重复配置的key={index}也会干扰React对节点匹配的判断。
  • 额外高频踩坑点:如果MyValues组件是定义在其他组件的函数作用域内部,每次父组件重渲染都会重新生成MyValues的组件引用,会导致整个组件树完全重挂载,必然丢焦点。
修复方式
  1. 给myValues数组的每一项配置稳定唯一标识(比如新增选项时生成时间戳/随机字符串作为id),遍历map时只用这个唯一id作为列表最外层元素的key,不要用数组下标。
  2. 删掉所有非列表直接子元素上的冗余key属性:包括外层列表容器上的key={myIndex}、内层Grid组件上重复添加的key={index},key只需要加在map遍历返回的第一个外层元素上即可。
  3. 把MyValues组件的定义提到父组件作用域外,保证组件引用稳定,不要嵌套在其他组件内部定义。
  4. 涉及数组增删操作时,通过唯一id定位对应项的索引,不要直接依赖遍历时候的index,避免操作错位。

修复后的参考代码:

// MyValues 定义在组件作用域外,保证引用稳定
const MyValues = ({ myGroup, name }) => (
  <FieldArray
    name={name}
    render={(arrayHelpers) => (      
      <>
        <div className={classes.dataSourceLayout}>
          {myGroup.myValues.map((myValue) => {
            // 提前定位当前项索引,供删除、字段名绑定使用
            const currentIndex = myGroup.myValues.findIndex(item => item.id === myValue.id)
            return (
              <div key={myValue.id}>
                <Grid container item spacing={6}>
                  <Grid item container spacing={1}>         
                    <Grid item xs={5}>
                      <Select
                        name={`${name}.${currentIndex}.job`}
                        label='Job'
                        options={jobs}
                      />
                    </Grid>
                    <Grid item xs={5}>
                      <TextField
                        name={`${name}.${currentIndex}.salary`}
                        label='Salary'
                      />
                    </Grid>
                    <Grid item xs={2}>
                      {myGroup.myValues.length > 1 && (
                        <Button                                
                          disableElevation
                          onClick={() => arrayHelpers.remove(currentIndex)}
                        >
                          <span>Delete</span>
                        </Button>
                      )}
                    </Grid>                    
                  </Grid>
                </Grid>
              </div>
            )
          })}
        </div>
      </>
    )} 
  />           
);

// 新增表单项时记得生成唯一id,示例:
// const addNewItem = () => {
//   arrayHelpers.push({
//     id: `salary_item_${Date.now()}`,
//     job: '',
//     salary: ''
//   })
// }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:24:18