一个屏幕上带有过滤器的多个React Admin列表

时间:2019-10-11 21:27:58

标签: reactjs react-admin

我们已经建立了一个基于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>
);

大多数似乎效果很好,但是过滤器使我们有些头疼。围绕它的所有内容似乎都是一次只为一个过滤器构建的,而没有任何自定义的方式(例如,在redux和react-router存储中指定要用于过滤器的属性,而不是使用硬编码的过滤器)

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

1 个答案:

答案 0 :(得分:1)

我最终想出一个我想分享的解决方法。

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

如果每个屏幕上只有一个列表,那是一件好事,但是在我们的情况下,一个列表的过滤器更新会导致将值反向传播到屏幕上的每个其他列表中。

首先,我尝试通过修改查询来保留所有过滤器,以使每个过滤器均使用其资源名称作为键。不幸的是,由于修补了RA内部,这引起了大量更改,包括复制整个RA组件。

NB:RA已经在其Redux存储中为每个资源保留了过滤器值,因此,为什么他们不对查询使用类似的语法/方法,这超出了我的理解。

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

以下是RA 3中的相关代码,该代码更新了查询:https://github.com/marmelab/react-admin/blob/master/packages/ra-core/src/controller/useListParams.ts#L164

history.push({
    search: `?${stringify({
        ...newParams,
        filter: JSON.stringify(newParams.filter),
        displayedFilters: JSON.stringify(newParams.displayedFilters),
    })}`,
});

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

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

const oldPush = history.push;
history.push = state => {
    oldPush({
        ...state,
        search: null,
    });
};

然后可以像这样使用它:

const App = () => (
    <Admin
        history={history}
        ...
    >
        ...
    </Admin>
);