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

React map渲染单选按钮时如何将其他已选项状态置为false

问题原因

当前实现无法实现单选互斥的核心原因是每个EachData组件各自维护独立的isOpen内部状态,组件之间没有状态同步机制,选中新的项时旧项的内部状态不会自动重置,就会出现多个项同时为激活态的问题。
另外你的代码还存在一个传参bug:子组件声明接收的prop名为open,但父组件遍历渲染时传入的是isOpen={false},导致子组件初始化时拿不到传入的open值。

修复方案

单选互斥类的场景,需要把「当前激活项」的状态提升到父组件统一管理,子组件只负责接收状态、触发回调,不自行维护互斥相关的状态。

1. 修改父组件App.js

在父组件中存储当前激活的编辑行索引,统一控制所有行的展开/收起状态:

import { useState } from 'react';
import EachData from './EachData';

function App() {
  // 替换为你实际使用的表格数据源
  const [tableData, setTableData] = useState([]);
  // 存储当前处于编辑激活状态的行索引,null表示无激活项
  const [activeEditIndex, setActiveEditIndex] = useState(null);

  const handleToggleEdit = (targetIndex) => {
    // 点击已激活的项则关闭,否则激活当前点击项,其余项自动变为未激活
    setActiveEditIndex(current => current === targetIndex ? null : targetIndex);
  };

  return (
    <table>
      <tbody>
        {tableData.map((data, index) => (
          <EachData
            // 建议用数据的唯一id作为key,不要直接用index,避免数据变动时状态错乱
            key={data.id || index}
            data={data}
            index={index}
            isOpen={activeEditIndex === index}
            onToggle={() => handleToggleEdit(index)}
          />
        ))}
      </tbody>
    </table>
  );
}

export default App;

2. 修改子组件EachData.jsx

移除子组件内部的独立状态,直接使用父组件传入的状态和回调即可:

function EachData({ data, index, isOpen, onToggle }) {
  return (
    <tr>
      {/* 其余td内容保持原样 */}
      <td>
        <div className="functions">
          {!isOpen ? (
            <>
              <label className="far fa-edit" htmlFor={`label-${index + 1}`}>
                <input
                  type="radio"
                  name="edit"
                  id={`label-${index + 1}`}
                  checked={isOpen}
                  onChange={onToggle}
                />
              </label>
              <label className="far fa-trash"></label>
            </>
          ) : (
            <>
              <label className="far fa-circle-check"></label>
              <label className="far fa-times-circle" htmlFor={`label-${index + 1}`}>
                <input
                  type="radio"
                  name="edit"
                  id={`label-${index + 1}`}
                  checked={isOpen}
                  onChange={onToggle}
                />
              </label>
            </>
          )}
        </div>
      </td>
    </tr>
  );
}

export default EachData;
修复后效果
  • 同一时间最多只有一行处于激活编辑状态,点击新的行会自动关闭之前激活的行
  • 点击已激活行的关闭按钮,可回到所有行均未激活的初始状态
  • 单选按钮的checked状态和React状态完全绑定,不会出现原生DOM状态和逻辑状态不一致的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:15:42