Reactjs 在一个屏幕上显示多个带有筛选器的React管理员列表

Reactjs 在一个屏幕上显示多个带有筛选器的React管理员列表,reactjs,react-admin,Reactjs,React Admin,我们已经基于React Admin构建了一个管理UI,为了方便起见,有几次我们希望在一个屏幕上使用多个列表。例如,在用户详细信息视图中,我们希望显示用户在文件中的多个地址,以及用户进行的购买。用户、地址和购买在RA术语中都是“资源” 大致如下: /* file <...>/resources/users/UserShow.js */ import AddressList from '../addresses/AddressList'; import PurchaseList fro

我们已经基于React Admin构建了一个管理UI,为了方便起见,有几次我们希望在一个屏幕上使用多个列表。例如,在用户详细信息视图中,我们希望显示用户在文件中的多个地址,以及用户进行的购买。用户、地址和购买在RA术语中都是“资源”

大致如下:

/* file <...>/resources/users/UserShow.js */

import AddressList from '../addresses/AddressList';
import PurchaseList from '../purchases/PurchaseList';

const UserShow = ({ id, classes, translate, ...props }) => (
    <Fragment>
        <Show id={id} {...props}>
            ...render user details here...
        </Show>
        <AddressList {...props} basePath={'/addresses'} resource={'addresses'} filter={{ userId: id }} />
        <PurchaseList {...props} basePath={'/purchases'} resource={'purchases'} filter={{ userId: id }} />
    </Fragment>
);
const App = () => (
    <Admin
        history={history}
        ...
    >
        ...
    </Admin>
);
/*文件/resources/users/UserShow.js*/
从“../addresses/AddressList”导入地址列表;
从“../PurchaseList/PurchaseList”导入PurchaseList;
const UserShow=({id,class,translate,…props})=>(
…在此处呈现用户详细信息。。。
);
大部分看起来都很好,但是过滤器让我们有些头疼。它周围的一切似乎一次只为一个过滤器构建,没有任何定制手段(例如,在redux和react路由器存储中指定用于过滤器的属性,而不是使用硬编码的属性)


有没有人曾经在同一屏幕上制作过两个可过滤列表,并且有更多的指针?

我最终想出了一个解决方案,我想与大家分享

问题是RA将过滤器/页面/排序值传播到查询中,并且它维护过滤器对象的“签名”(对应JSON的字符串表示),以在URL更改时检测当前过滤器中的更改。使用这种方法,当用户来回导航时,过滤器和分页值保持活动状态,并且只有在实际字段值更改时才会更新

如果每个屏幕上都有一个列表,这是一件好事,但在我们的例子中,一个列表的过滤器更新会导致值反向传播到屏幕上的每个其他列表中

首先,我试图通过修改查询来保留所有筛选器,以便每个筛选器都使用其资源名称作为密钥。不幸的是,由于修补RAs内部,这导致了大量的更改,包括复制整个RA组件

注意:RA已经在其Redux存储中保留了每个资源的筛选器值,因此我无法理解为什么它们不使用类似的语法/方法进行查询

另一种选择是完全切断向查询的传播。折衷的办法是,您不能为特定的搜索添加书签,并且在导航时需要重新激活过滤器,但这似乎是一个可以接受的小缺点

以下是RA 3中更新查询的相关代码:

无法直接修改此行为,但我们可以向RA提供自己的历史实现,并覆盖搜索参数。相应的猴子补丁如下所示:

const history = createBrowserHistory({
    basename: process.env.PUBLIC_URL
});

const oldPush = history.push;
history.push = state => {
    oldPush({
        ...state,
        search: null,
    });
};
然后可以这样使用:

/* file <...>/resources/users/UserShow.js */

import AddressList from '../addresses/AddressList';
import PurchaseList from '../purchases/PurchaseList';

const UserShow = ({ id, classes, translate, ...props }) => (
    <Fragment>
        <Show id={id} {...props}>
            ...render user details here...
        </Show>
        <AddressList {...props} basePath={'/addresses'} resource={'addresses'} filter={{ userId: id }} />
        <PurchaseList {...props} basePath={'/purchases'} resource={'purchases'} filter={{ userId: id }} />
    </Fragment>
);
const App = () => (
    <Admin
        history={history}
        ...
    >
        ...
    </Admin>
);
const-App=()=>(
...
);