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

React表格单元格二次点击可编辑功能异常求助

React表格单元格双击编辑功能异常排查

问题场景

需要实现:第一次点击表格单元格时,单元格获得焦点(高亮);第二次点击同一单元格时,输入框获得焦点并可编辑。但当前代码需要多次点击才会显示可编辑输入框。

错误分析

  1. 状态逻辑混淆:仅用currentIndex一个状态同时管理「选中」和「编辑」两种状态,导致第一次点击就直接渲染输入框,不符合“先选中、再编辑”的需求,同时因React状态更新的异步特性,容易出现点击响应延迟的问题。
  2. 输入框只读判断冗余:输入框的readOnly属性依赖与显示输入框相同的条件,逻辑重复且不合理。
  3. 状态更新不规范:修改表格数据时仅做了数组的浅拷贝,内层对象仍为原引用,虽然能触发更新,但不符合React状态不可变的原则,可能引发潜在的状态异常。

修正方案

拆分状态,分别管理「选中单元格」和「编辑单元格」,同时规范状态更新逻辑:

修正后的完整代码

import React, { useState } from 'react';

function App() {
  // 存储选中的单元格(仅高亮)
  const [selectedCell, setSelectedCell] = useState(null);
  // 存储正在编辑的单元格
  const [editingCell, setEditingCell] = useState(null);

  const [array, setArray] = useState(Array.from({ length: 4 }, () =>
    Array.from({ length: 4 }, () => ({
      color: "",
      text: "",
    }))
  ));

  function selectCell(row, col) {
    // 点击已选中的单元格,进入编辑状态
    if (selectedCell?.row === row && selectedCell?.col === col) {
      setEditingCell({ row, col });
    } else {
      // 点击未选中的单元格,切换选中状态并退出编辑
      setSelectedCell({ row, col });
      setEditingCell(null);
    }
  }

  function handleText(text, row, col) {
    // 规范状态更新:深拷贝二维数组及内层对象
    const newArray = array.map(rowItem => 
      rowItem.map(cell => ({ ...cell }))
    );
    newArray[row][col].text = text;
    setArray(newArray);
  }

  function changeColor(color) {
    if (selectedCell) {
      const newArray = array.map(rowItem => 
        rowItem.map(cell => ({ ...cell }))
      );
      newArray[selectedCell.row][selectedCell.col].color = color;
      setArray(newArray);
    }
  }

  return (
    <div className="App" style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
      <div style={{ marginTop: "100px" }}>
        <button onClick={() => changeColor("red")}>Red</button>
        <button onClick={() => changeColor("blue")}>Blue</button>
        <button onClick={() => changeColor("green")}>Green</button>
      </div>

      <div style={{ marginTop: "100px" }}>
        {array.map((arr, rowIndex) => (
          <div key={rowIndex} style={{ display: "flex" }}>
            {arr.map((item, colIndex) => (
              <div
                onClick={() => selectCell(rowIndex, colIndex)}
                key={colIndex}
                style={{
                  width: 100,
                  height: 50,
                  margin: 2,
                  display: 'flex',
                  alignItems: "center",
                  justifyContent: "center",
                  backgroundColor: item.color,
                  border: selectedCell && selectedCell.row === rowIndex && selectedCell.col === colIndex ? "2px solid black" : "1px solid black"
                }}
              >
                {editingCell && editingCell.row === rowIndex && editingCell.col === colIndex ? (
                  <input
                    type="text"
                    style={{ width: 90, height: 40, backgroundColor: item.color }}
                    value={item.text}
                    autoFocus // 编辑时自动获取焦点
                    onChange={(e) => handleText(e.target.value, rowIndex, colIndex)}
                  />
                ) : `${item.text}`}
              </div>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;

关键修改点

  • 新增selectedCell和editingCell两个状态,分别管理选中和编辑状态,实现“第一次点击选中、第二次点击编辑”的逻辑。
  • 输入框添加autoFocus属性,进入编辑时自动获取焦点,提升交互体验。
  • 状态更新时采用深拷贝方式,确保React状态的不可变性,避免潜在异常。
  • 移除冗余的readOnly判断,编辑状态下直接渲染可编辑的输入框。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:39:51