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

如何在遍历未知长度数组时实现每行仅选一个MUI ToggleButton

解决MUI ToggleButtonGroup每行独立单选的问题

问题描述

我正在用MUI和React做赛事选择组件,每个赛事行(主胜、平局、客胜)用ToggleButton展示,要求每行只能选一个选项。赛事每周都会变,数量也不固定。
默认的ToggleButtonGroup是全局只能选一个,我把exclusive改成false后,虽然支持数组,但用户能在同一行选多个结果,不符合需求。
怎么加逻辑实现每行独立单选?

注意:赛事数据来自数据库调用,下面的fixtures数组是返回数据的示例。
ToggleButton展示赛事的效果

用户原代码:

const [fixtures, SetFixtures] = useState([{
    gameweek: "loading...", game: "loading...", home: "loading...",
    away: "loading...", draw: "loading...", kickoff_datetime: "loading...", result: "loading...",
  }]);
const [alignment, setAlignment] = useState([]);


const handleChange = (newAlignment) => {
    setAlignment(newAlignment);
  };


const fixtures = [
      { game: "LeicesterArsenal", gameweek: 2, home: "Leicester", away: "Arsenal", draw:"LeicesterArsenalDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
      { game: "ManchesterUnitedNottinghamForest", game: 2, home: "Manchester United", away: "Nottingham Forest", draw:"ManchesterUnitedNottinghamForestDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
      { game: "TottenhamWestHam", game: 2, home: "Tottenham", away: "West Ham", draw:"TottenhamWestHamDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
      { game: "WolvesCrystalPalace", game: 2, home: "Wolves", away: "Crystal Palace", draw:"WolvesCrystalPalaceDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }]


function RenderFixtures() {
    return fixtures.map((fixture, index) =>
      <div id={"fixture-row-" + index} key={fixture.game}>
      <ToggleButtonGroup
        color="success"
        value={alignment}
        exclusive={true}
        onChange={handleChange}
      >
        <ToggleButton value={fixture.home}>{fixture.home}</ToggleButton>
        <ToggleButton value={fixture.draw}>Draw</ToggleButton>
        <ToggleButton value={fixture.away}>{fixture.away}</ToggleButton>
        </ToggleButtonGroup>
      </div>

解决方案

核心问题是你用了全局的alignment状态管理所有行的选中状态,导致所有ToggleButtonGroup共享同一状态。要实现每行独立单选,需给每个赛事行分配单独的状态:

  • 修改状态结构:把全局数组改成对象,用赛事的唯一标识(比如fixture.game)作为key,存储对应行的选中值
  • 更新事件处理函数:让它能针对具体赛事更新状态
  • 绑定每行独立状态:每个ToggleButtonGroup使用对应赛事的状态值,保持exclusive={true}确保行内单选

修改后的完整代码示例:

import { useState } from 'react';
import { ToggleButtonGroup, ToggleButton } from '@mui/material';

const YourComponent = () => {
  // 初始化赛事状态,加载时显示占位内容
  const [fixtures, setFixtures] = useState([{
    gameweek: "loading...", game: "loading...", home: "loading...",
    away: "loading...", draw: "loading...", kickoff_datetime: "loading...", result: "loading...",
  }]);

  // 用对象存储每行的选中状态,key为赛事唯一标识
  const [selections, setSelections] = useState({});

  // 处理每行的选择变化,传入赛事唯一标识
  const handleChange = (event, newSelection, fixtureKey) => {
    setSelections(prevState => ({
      ...prevState,
      [fixtureKey]: newSelection || null
    }));
  };

  // 示例赛事数据(实际从数据库获取后用setFixtures更新)
  const sampleFixtures = [
    { game: "LeicesterArsenal", gameweek: 2, home: "Leicester", away: "Arsenal", draw:"LeicesterArsenalDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
    { game: "ManchesterUnitedNottinghamForest", gameweek: 2, home: "Manchester United", away: "Nottingham Forest", draw:"ManchesterUnitedNottinghamForestDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
    { game: "TottenhamWestHam", gameweek: 2, home: "Tottenham", away: "West Ham", draw:"TottenhamWestHamDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }, 
    { game: "WolvesCrystalPalace", gameweek: 2, home: "Wolves", away: "Crystal Palace", draw:"WolvesCrystalPalaceDraw", kickoff_datetime: "2022-07-15T15:30:00", result: null }
  ];

  // 渲染赛事行
  function RenderFixtures() {
    return fixtures.map((fixture) => (
      <div id={`fixture-row-${fixture.game}`} key={fixture.game}>
        <ToggleButtonGroup
          color="success"
          value={selections[fixture.game] || null}
          exclusive={true}
          onChange={(e, val) => handleChange(e, val, fixture.game)}
        >
          <ToggleButton value={fixture.home}>{fixture.home}</ToggleButton>
          <ToggleButton value={fixture.draw}>Draw</ToggleButton>
          <ToggleButton value={fixture.away}>{fixture.away}</ToggleButton>
        </ToggleButtonGroup>
      </div>
    ));
  }

  return (
    <div>
      {RenderFixtures()}
    </div>
  );
};

export default YourComponent;

关键说明

  1. 状态selections是对象,每个key对应一个赛事的选中值,确保各行状态独立
  2. 每个ToggleButtonGroup的value绑定selections[fixture.game],只关注当前行的选中状态
  3. handleChange通过fixtureKey精准更新对应赛事的选中值,不影响其他行
  4. 保持exclusive={true},确保每行内部只能选择一个选项

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 03:54:15