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
相关产品推荐
相关产品推荐

