基于record值控制react-admin组件显示的问题求助
问题分析与解决方案
你的核心问题是错误地在非行级组件层级使用useRecordContext,导致无法获取到列表中单行的record数据,进而无法根据每条记录的情况控制编辑按钮的显示。
错误原因拆解
useRecordContext只能在列表的行级组件(比如Datagrid的子列组件、每行内部的自定义组件)中使用,因为List是整个列表的容器,它的上下文没有单个record,只有渲染到每行时,react-admin才会注入当前行的record上下文。- 你在
App和createResources层级传递record的逻辑完全无效,这些位置根本没有单个记录的数据,自然拿到的record是undefined。
正确实现方式
我们需要自定义一个行级的条件编辑按钮组件,在组件内部获取当前行的record并判断权限。
1. 自定义条件编辑按钮
import { EditButton, useRecordContext, usePermissions } from 'react-admin'; // 自定义带条件判断的编辑按钮 const ConditionalEditButton = ({ resourceName }) => { const record = useRecordContext(); // 这里能拿到当前行的record const { permissions } = usePermissions(); // 结合全局权限和当前record的字段判断是否显示按钮 if (!hasPermission(`${resourceName}.edit`, permissions, record)) { return null; } return <EditButton />; };
2. 修改列表组件,移除无效的record传递
const AiohttpList = (resource, name, permissions) => ( <List filters={createInputs(resource, name, "view", permissions)}> <Datagrid rowClick="show"> {createFields(resource, name, permissions, true)} {/* 使用自定义的条件按钮 */} <ConditionalEditButton resourceName={name} /> </Datagrid> </List> );
3. 修正资源创建逻辑,去掉无用的record参数
function createResources(resources, permissions) { let components = []; for (const [name, r] of Object.entries(resources)) { components.push(<Resource name={name} create={hasPermission(`${name}.add`, permissions) ? AiohttpCreate(r, name, permissions) : null} edit={hasPermission(`${name}.edit`, permissions) ? AiohttpEdit(r, name, permissions) : null} list={hasPermission(`${name}.view`, permissions) ? AiohttpList(r, name, permissions) : null} show={hasPermission(`${name}.view`, permissions) ? AiohttpShow(r, name, permissions) : null} />); } return components; }
4. 简化App组件,移除无效的useRecordContext调用
const App = () => { return (<Admin dataProvider={dataProvider} authProvider={authProvider}> {permissions => createResources(STATE["resources"], permissions)} </Admin>); };
补充:完善hasPermission函数
确保你的hasPermission函数能结合record的字段做判断,比如根据记录的状态控制编辑权限:
function hasPermission(permissionKey, permissions, record) { // 先判断全局权限是否存在 if (!permissions.includes(permissionKey)) { return false; } // 再根据当前record的字段判断(示例:仅状态为active的记录允许编辑) if (record && record.status !== "active") { return false; } return true; }
内容的提问来源于stack exchange,提问作者Sam Bull
相关产品推荐
相关产品推荐

