【问题标题】:Can you share your dataProvider with client-side sorting and filtering?您可以与客户端排序和过滤共享您的 dataProvider 吗?
【发布时间】:2020-07-10 13:06:40
【问题描述】:

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

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

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

提前感谢您的任何帮助!

【问题讨论】:

    标签: react-admin


    【解决方案1】:

    这是我为我们的项目编写的 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-11
      • 2015-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 2020-09-09
      相关资源
      最近更新 更多