首页 > 解决方案 > 您可以与客户端排序和过滤共享您的 dataProvider 吗?

问题描述

我有一个我正在使用的基本 REST API(没有查询,没有分页),并且我将它很好地集成到了 React Admin 中,具有编辑、显示和创建操作。一切都很好。但是,我的 API 没有任何过滤或排序功能,因此Datagrid失去了功能,因为我无法搜索或排序列。

我知道我需要自己实现客户端函数来过滤和排序 API 中的自定义dataProvider. 与其从头开始构建这一切,任何人都可以dataProvider与我分享他们已经具有本地排序、过滤器等的自定义,我可以适应而不是从头开始构建吗?

或者,我昨晚为 React 实现了 Tubular,我喜欢它的易用性,但它缺乏与 React Admin 的良好集成。有没有人在 React Admin 中实现了 Tubular,你是如何实现的?

提前感谢您的任何帮助!!

标签: react-admin

解决方案


这是我为我们的项目编写的 dataProvider。所有的过滤、排序、分页都是在客户端完成的。

import { fetchUtils, DataProvider } from 'ra-core';

const dataProvider = (apiUrl : string, httpClient = fetchUtils.fetchJson) : DataProvider => ({
    getList: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`);
        const feedFilter = params.filter["feed"];
        const stateFilter = params.filter["state"];

        const result = json
            .filter(e => {
                if (!feedFilter) {
                    return true;
                }
                return e.feed.includes(feedFilter.toUpperCase());
            })
            .filter(e => {
                if (!stateFilter) {
                    return true;
                }
                return e.state === stateFilter;
            });

        const { field, order } = params.sort;
        result.sort(dynamicSort(field, order));

        const { page, perPage } = params.pagination;
        const showedResult = result.slice((page - 1) * perPage, page * perPage);

        return {
            data: showedResult.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
            total: result.length,
        };
    },

    getMany: async (resource) => {
        const url = `${ apiUrl }/${ resource }`;
        const { json } = await httpClient(url);
        return ({
            data: json.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
        });
    },

    getManyReference: async (resource) => {
        const url = `${ apiUrl }/${ resource }`;

        const { headers, json } = await httpClient(url);
        return ({
            data: json.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
            total: parseInt(headers.get('X-Total-Count') || "", 10),
        });
    },

    getOne: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`).then(({ json }) => ({
            data: json,
        })),

    update: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`, {
            method: 'PUT',
            body: JSON.stringify(params.data),
        }).then(({ json }) => ({ data: json })),

    updateMany: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`, {
            method: 'PUT',
            body: JSON.stringify(params.data),
        });
        return ({ data: json });
    },

    create: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }`, {
            method: 'POST',
            body: JSON.stringify(params.data),
        }).then(({ json }) => ({
            data: { ...params.data, id: json.id },
        })),

    delete: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`, {
            method: 'DELETE',
        }).then(({ json }) => ({ data: json })),

    deleteMany: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`, {
            method: 'DELETE',
            body: JSON.stringify(params.ids),
        });
        return ({ data: json });
    },
});

function dynamicSort(property : string, order : string){
    let sortOrder = 1;
    if (order === "DESC") {
        sortOrder = -1;
    }
    return function (a : any, b : any){
        let aProp = a[property];
        let bProp = b[property];
        if (!a.hasOwnProperty(property)) {
            aProp = ''
        }
        if (!b.hasOwnProperty(property)) {
            bProp = ''
        }
        const result = (aProp < bProp) ? -1 : (aProp > bProp) ? 1 : 0;
        return result * sortOrder;
    }
}

const cacheDataProviderProxy = (dataProvider : any, duration = 5 * 60 * 1000) =>
    new Proxy(dataProvider, {
        get: (dataProvider, name) => (resource : string, params : any) => {
            if (name === 'getOne' || name === 'getMany' || name === 'getList') {
                return dataProvider.name(resource, params).then((response : { validUntil : Date; }) => {
                    const validUntil = new Date();
                    validUntil.setTime(validUntil.getTime() + duration);
                    response.validUntil = validUntil;
                    return response;
                });
            }
            return dataProvider.name(resource, params);
        },
    });

export default cacheDataProviderProxy(dataProvider);

推荐阅读