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

React Table仅首次选中行点Apply前变灰 后续行直接隐藏问题

问题描述
  • 点击Show列下方的开关控件时,首次操作(例如操作Potato Soup对应的开关)整行会显示灰色选中背景,点击Apply按钮后该行被隐藏,表现符合预期。
  • 后续对Pea Soup等其他行执行相同操作时,选中的行不会先显示灰色背景,点击Apply后会直接被隐藏。
  • 期望行为:第二次及之后选中行时也能正常展示灰色选中态,点击Apply后再执行隐藏逻辑。

效果示意图

问题复现代码

export default function MenuDisplay() {
  const { menuId } = useParams();
  const { match } = JsonData;

  const [hideSelected, setHideSelected] = useState(false);
  const [selected, setSelected] = useState({});

  const rowSelectHandler = (id) => (checked) => {
    setSelected((selected) => ({
      ...selected,
      [id]: checked
    }));
  };

  const toggleShow = () => setHideSelected((hide) => !hide);

  const matchData = (
    match.find((el) => el._id_menu === menuId)?._ids ?? []
  ).filter(({ _id }) => {
    if (hideSelected) {
      return !selected[_id];
    }
    return true;
  });

  const getRowProps = (row) => {
    return {
      style: {
        backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
      }
    };
  };

  const data = [
    {
      Header: "id",
      accessor: (row) => row._id
    },
    {
      Header: "Name",
      accessor: (row) => (
        <Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
      )
    },
    {
      Header: "Description",
      accessor: (row) => row.description
    },
    {
      Header: "Dishes",
      accessor: (row) => row.dishes,
      id: "dishes",
      Cell: ({ value }) => value && Object.values(value[0]).join(", ")
    },
    {
      Header: "Show",
      accessor: (row) => (
        <Toggle
          value={selected[row._id]}
          onChange={rowSelectHandler(row._id)}
        />
      )
    }
  ];

  const initialState = {
    sortBy: [
      { desc: false, id: "id" },
      { desc: false, id: "description" }
    ],
    hiddenColumns: ["dishes", "id"]
  };

  return (
    <div>
      <Button primary onClick={toggleShow}>
        {hideSelected ? "Cancel" : "Apply"}
      </Button>
      <Table
        data={matchData}
        columns={data}
        initialState={initialState}
        withCellBorder
        withRowBorder
        withSorting
        withPagination
        rowProps={getRowProps}
      />
    </div>
  );
}
问题根因

问题出在选中行背景色的取值判断逻辑上:

  1. getRowProps中通过selected[row.values.id]判断当前行是否选中,这里的row.values是react-table根据列配置生成的单元格值集合,取值完全依赖列id配置的稳定性。
  2. 定义id列时,accessor传入的是函数,但没有显式指定列的id属性。react-table对于使用函数作为accessor的列,要求必须手动配置id作为列的唯一标识,首次渲染时碰巧能正确生成id为id的列值,所以首次操作表现正常。
  3. 点击Apply后表格数据被过滤,触发表格重渲染,此时未显式指定id的列无法稳定生成对应值,row.values.id返回undefined,导致selected[undefined]始终为假值,灰色背景的判断逻辑直接失效。
修复方案

做两处调整即可彻底解决问题:

  1. 给id列显式添加id配置,保证列标识全局稳定
  2. (推荐)行属性判断时直接从行实例的original字段取原始数据的id,不依赖列生成的values集合,从根源避免列配置变动带来的取值问题

修复后的核心代码如下:

const getRowProps = (row) => {
  return {
    style: {
      // 直接从原始行数据取_id,不依赖row.values的生成结果
      backgroundColor: selected[row.original._id] ? "lightgrey" : "white"
    }
  };
};

const data = [
  {
    Header: "id",
    accessor: (row) => row._id,
    id: "id" // 显式指定列id,保证列标识稳定
  },
  // 其余列配置保持不变
  // ...
];

修复后,无论进行多少次选中、Apply隐藏操作,选中行的灰色高亮效果都能正常展示,点击Apply后才会执行隐藏逻辑,完全符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:31:06