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

基于record值控制react-admin组件显示的问题求助

问题分析与解决方案

你的核心问题是错误地在非行级组件层级使用useRecordContext,导致无法获取到列表中单行的record数据,进而无法根据每条记录的情况控制编辑按钮的显示。

错误原因拆解

  1. useRecordContext只能在列表的行级组件(比如Datagrid的子列组件、每行内部的自定义组件)中使用,因为List是整个列表的容器,它的上下文没有单个record,只有渲染到每行时,react-admin才会注入当前行的record上下文。
  2. 你在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:37:44