【问题标题】:Multiple React Admin Lists with filters on one screen一个屏幕上有多个带有过滤器的 React 管理员列表
【发布时间】:2019-10-11 21:27:58
【问题描述】:

我们已经基于 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 存储中指定用于过滤器的属性,而不是使用硬编码的)

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

【问题讨论】:

    标签: reactjs react-admin


    【解决方案1】:

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

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

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

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

    注意: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>
    );
    

    【讨论】:

      猜你喜欢
      • 2018-02-15
      • 2013-09-16
      • 2011-01-23
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多