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

React+MUI项目:解决表格内TextField编辑时失焦的问题

解决MUI表格中TextField编辑时失焦问题

我在开发一款HR网页应用的问卷创建功能,用MUI组件实现了展示问卷问题的表格,支持修改问题文本,但遇到一个问题:每次编辑TextField时,输入框都会失去焦点,仅在TextField嵌套于表格内时出现这个现象。

相关代码如下:

import TableContainer from "@mui/material/TableContainer";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableRow from "@mui/material/TableRow";
import TableCell from "@mui/material/TableCell";
import TextField from "@mui/material/TextField";
import { styled } from "@mui/system";
import { useState } from "react";

export default function TableTextFieldTest() {
    const [questions, setQuestions] = useState([
        {
            index: 0,
            question: "Do you have any feedback on your manager or team that you'd like to share?",
        },
        {
            index: 1,
            question: "What suggestions do you have for improving the company culture or work environment?",
        },
        {   
            index: 2,
            question: "How was your experience working here?",
        }
    ]);

    //Custom style elements
    const TableBodyCell = styled(TableCell)({
        paddingLeft: "24px",
        paddingRight: "24px",
        paddingTop: "16px",
        paddingBottom: "16px"
    });

    //Handle changes to the textfield when editing a survey question
    function handleEditTextfield(e, index) {
        const newQuestions = Array.from(questions);
        const q = newQuestions.find((q) => q.index === index);
        q.question = e.target.value;
        setQuestions(newQuestions);
    };

    return (
        <TableContainer>
            <Table>
                <TableBody>
                    {questions.sort((q1, q2) => q1.index - q2.index).map((q, index) => (
                        <TableRow>
                            <TableBodyCell>
                                <TextField 
                                    value={q.question}
                                    onChange={(e) => handleEditTextfield(e, index)}
                                    sx={{ width: "100%" }}
                                />
                            </TableBodyCell>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </TableContainer>
    );
};

问题原因

  1. 不稳定的key值:map遍历依赖数组索引作为隐式key,每次修改问题触发state更新后,sort操作会改变数组元素顺序,导致React无法识别组件的稳定性,强制重新渲染并丢失焦点。
  2. 内部定义的styled组件:TableBodyCell定义在组件内部,每次组件渲染都会重新创建这个styled组件,React会认为这是全新的组件类型,卸载旧组件并挂载新组件,直接导致焦点丢失。
  3. 索引匹配错误:handleEditTextfield中传入的是map的数组索引,但查找时用的是问题对象自身的index属性,当数组排序后两者可能不匹配,导致更新逻辑混乱,间接引发渲染异常。

解决方案

  1. 使用稳定的key:给TableRow设置唯一且稳定的key,直接使用问题对象的index属性(确保其唯一性)。
  2. 将styled组件移到外部:把TableBodyCell定义在组件外部,避免每次渲染重新创建。
  3. 修正索引传递:在onChange中传递问题对象的index属性,而非map的数组索引,确保更新逻辑准确。

修改后的完整代码

import TableContainer from "@mui/material/TableContainer";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableRow from "@mui/material/TableRow";
import TableCell from "@mui/material/TableCell";
import TextField from "@mui/material/TextField";
import { styled } from "@mui/system";
import { useState } from "react";

// 将styled组件移到组件外部
const TableBodyCell = styled(TableCell)({
    paddingLeft: "24px",
    paddingRight: "24px",
    paddingTop: "16px",
    paddingBottom: "16px"
});

export default function TableTextFieldTest() {
    const [questions, setQuestions] = useState([
        {
            index: 0,
            question: "Do you have any feedback on your manager or team that you'd like to share?",
        },
        {
            index: 1,
            question: "What suggestions do you have for improving the company culture or work environment?",
        },
        {   
            index: 2,
            question: "How was your experience working here?",
        }
    ]);

    function handleEditTextfield(e, questionIndex) {
        const newQuestions = [...questions]; // 用展开运算符更简洁
        const q = newQuestions.find((q) => q.index === questionIndex);
        if (q) { // 增加判断避免找不到的情况
            q.question = e.target.value;
            setQuestions(newQuestions);
        }
    };

    return (
        <TableContainer>
            <Table>
                <TableBody>
                    {questions.sort((q1, q2) => q1.index - q2.index).map((q) => (
                        <TableRow key={q.index}> {/* 使用稳定的key */}
                            <TableBodyCell>
                                <TextField 
                                    value={q.question}
                                    onChange={(e) => handleEditTextfield(e, q.index)} {/* 传递问题自身的index */}
                                    sx={{ width: "100%" }}
                                />
                            </TableBodyCell>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </TableContainer>
    );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:58:18