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

React-Admin Datagrid isRowSelectable配置与全选复选框问题解决

解决方案

1. 解决全选时的钩子调用错误

错误原因

你的checkAllStatuses函数内部调用了useListContext,但它作为isRowSelectable的参数被Datagrid在非组件渲染上下文执行,违反了React Hook的调用规则——Hook只能在组件或自定义Hook的顶层调用。

修复代码

将Hook调用移到组件内部,在顶层获取数据并计算状态,再传给isRowSelectable:

import { List, Datagrid, useListContext, useMemo } from 'react-admin';

const EmployeeList = (props) => {
  // 在组件顶层调用Hook,符合规则
  const { data } = useListContext();

  // 用useMemo缓存计算结果,避免重复计算
  const allStatusesSame = useMemo(() => {
    if (!data || data.length === 0) return false;
    const uniqueStatuses = [...new Set(data.map(item => item.status))];
    return uniqueStatuses.length === 1;
  }, [data]);

  return (
    <List title="Employees">
      <Datagrid 
        // isRowSelectable返回全局判断结果,所有行的可选状态一致
        isRowSelectable={() => allStatusesSame}
      >
        {/* 你的列定义 */}
      </Datagrid>
    </List>
  );
};

2. 禁用/隐藏全选复选框

方法一:禁用全选复选框

通过自定义选择列,根据状态控制全选按钮的禁用状态:

import { DatagridSelectColumn, useListContext, useSelectAllContext, useMemo } from 'react-admin';

const CustomSelectColumn = ({ ...props }) => {
  const { data } = useListContext();
  const allStatusesSame = useMemo(() => {
    if (!data || data.length === 0) return false;
    const uniqueStatuses = [...new Set(data.map(item => item.status))];
    return uniqueStatuses.length === 1;
  }, [data]);

  const { selectAll, selectedIds } = useSelectAllContext();
  const isAllSelected = allStatusesSame && selectedIds.size === data.length;

  return (
    <DatagridSelectColumn
      {...props}
      selectAllCheckboxProps={{
        disabled: !allStatusesSame,
        checked: isAllSelected,
        onChange: (e) => allStatusesSame && selectAll(e.target.checked)
      }}
    />
  );
};

// 在EmployeeList中使用自定义列
const EmployeeList = (props) => {
  const { data } = useListContext();
  const allStatusesSame = useMemo(() => {
    if (!data || data.length === 0) return false;
    const uniqueStatuses = [...new Set(data.map(item => item.status))];
    return uniqueStatuses.length === 1;
  }, [data]);

  return (
    <List title="Employees">
      <Datagrid 
        isRowSelectable={() => allStatusesSame}
        select={<CustomSelectColumn />}
      >
        {/* 你的列定义 */}
      </Datagrid>
    </List>
  );
};

方法二:隐藏全选复选框(及整个选择列)

如果需要在状态不一致时完全隐藏选择列,修改自定义列的渲染逻辑:

const CustomSelectColumn = ({ ...props }) => {
  const { data } = useListContext();
  const allStatusesSame = useMemo(() => {
    if (!data || data.length === 0) return false;
    const uniqueStatuses = [...new Set(data.map(item => item.status))];
    return uniqueStatuses.length === 1;
  }, [data]);

  // 状态不一致时不渲染选择列
  if (!allStatusesSame) return null;

  return <DatagridSelectColumn {...props} />;
};

这样当所有行status不一致时,全选复选框和每行的选择框都会被隐藏,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:23:30