【问题标题】:Inconsistency of default sort, pagination parameters name and logic in React AdminReact Admin 中默认排序、分页参数名称和逻辑不一致
【发布时间】:2020-08-31 23:37:48
【问题描述】:

我有一个简单的前端 react-admin 应用,带有一个 Flask API,我正在尝试在我的 API 中实现排序、过滤和分页。

我正在使用dataprovider ra-data-json-server,根据this spec,我必须使用“_sort”、“_start”和“_end”参数(带下划线)来实现它。

但是,当我查看我的 Front 应用程序执行的 GET 查询时,排序和分页将类似于:

https://balbla.com/#/users?filter=%7B%7D&order=ASC&page=1&perPage=10&sort=roles

这与那里的文档一致https://marmelab.com/react-admin/DataProviders.html

所以我很困扰,因为:

  • 参数名称不同(下划线)
  • 分页逻辑完全不同(结束和开始与页码和页长)。

是我遗漏了什么还是确实存在不一致之处?执行哪一个?对我来说,最简单的方法是让我的后端适应实际的 Front 查询格式,但这不是文档。

谢谢

【问题讨论】:

    标签: react-admin


    【解决方案1】:

    一开始我也有和你一样的困惑,然后我发现了 ra-data-json-server 的源代码。它实现了 _sort、_order、_start 和 _end。首先,您需要在 API 中实现排序和分页。我会建议你在下面使用这个 ra-data-json-server 数据提供者:

    import { stringify } from "query-string";
    import { fetchUtils } from "ra-core";
    /**
     * Maps react-admin que`enter code here`ries to a json-server powered REST API
     *
     * @see https://github.com/typicode/json-server
     *
     * @example
     *
     * getList          => GET http://my.api.url/posts?_sort=title&_order=ASC&_start=0&_end=24
     * getOne           => GET http://my.api.url/posts/123
     * getManyReference => GET http://my.api.url/posts?author_id=345
     * getMany          => GET http://my.api.url/posts/123, GET http://my.api.url/posts/456, GET http://my.api.url/posts/789
     * create           => POST http://my.api.url/posts/123
     * update           => PUT http://my.api.url/posts/123
     * updateMany       => PUT http://my.api.url/posts/123, PUT http://my.api.url/posts/456, PUT http://my.api.url/posts/789
     * delete           => DELETE http://my.api.url/posts/123
     *
     * @example
     *
     * import React from 'react';
     * import { Admin, Resource } from 'react-admin';
     * import jsonServerProvider from 'ra-data-json-server';
     *
     * import { PostList } from './posts';
     *
     * const App = () => (
     *     <Admin dataProvider={jsonServerProvider('http://jsonplaceholder.typicode.com')}>
     *         <Resource name="posts" list={PostList} />
     *     </Admin>
     * );
     *
     * export default App;
     */
    var __assign =
      (this && this.__assign) ||
      function () {
        __assign =
          Object.assign ||
          function (t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
              s = arguments[i];
              for (var p in s)
                if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
            }
            return t;
          };
        return __assign.apply(this, arguments);
      };
    
    export default (function (apiUrl, httpClient) {
      if (httpClient === void 0) {
        httpClient = fetchUtils.fetchJson;
      }
      return {
        getList: function (resource, params) {
          var _a = params.pagination,
            page = _a.page,
            perPage = _a.perPage;
          var _b = params.sort,
            field = _b.field,
            order = _b.order;
          var query = __assign(
            __assign({}, fetchUtils.flattenObject(params.filter)),
            {
              _sort: field,
              _order: order,
              _start: (page - 1) * perPage + 1,
              _end: page * perPage,
            }
          );
          var url = apiUrl + "/" + resource + "?" + stringify(query);
          return httpClient(url).then(function (_a) {
            var headers = _a.headers,
              json = _a.json;
            if (!headers.has("x-total-count")) {
              throw new Error(
                "The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?"
              );
            }
            return {
              data: json,
              total: parseInt(headers.get("x-total-count").split("/").pop(), 10),
            };
          });
        },
        getOne: function (resource, params) {
          return httpClient(apiUrl + "/" + resource + "/" + params.id).then(
            function (_a) {
              var json = _a.json;
              return {
                data: json,
              };
            }
          );
        },
        getMany: function (resource, params) {
          var query = {
            id: params.ids,
          };
          var url = apiUrl + "/" + resource + "?" + stringify(query);
          return httpClient(url).then(function (_a) {
            var json = _a.json;
            return { data: json };
          });
        },
        getManyReference: function (resource, params) {
          var _a;
          var _b = params.pagination,
            page = _b.page,
            perPage = _b.perPage;
          var _c = params.sort,
            field = _c.field,
            order = _c.order;
          var query = __assign(
            __assign({}, fetchUtils.flattenObject(params.filter)),
            ((_a = {}),
            (_a[params.target] = params.id),
            (_a._sort = field),
            (_a._order = order),
            (_a._start = (page - 1) * perPage),
            (_a._end = page * perPage),
            _a)
          );
          var url = apiUrl + "/" + resource + "?" + stringify(query);
          return httpClient(url).then(function (_a) {
            var headers = _a.headers,
              json = _a.json;
            if (!headers.has("x-total-count")) {
              throw new Error(
                "The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?"
              );
            }
            return {
              data: json,
              total: parseInt(headers.get("x-total-count").split("/").pop(), 10),
            };
          });
        },
        update: function (resource, params) {
          return httpClient(apiUrl + "/" + resource + "/" + params.id, {
            method: "PUT",
            body: JSON.stringify(params.data),
          }).then(function (_a) {
            var json = _a.json;
            return { data: json };
          });
        },
        // json-server doesn't handle filters on UPDATE route, so we fallback to calling UPDATE n times instead
        updateMany: function (resource, params) {
          return Promise.all(
            params.ids.map(function (id) {
              return httpClient(apiUrl + "/" + resource + "/" + id, {
                method: "PUT",
                body: JSON.stringify(params.data),
              });
            })
          ).then(function (responses) {
            return {
              data: responses.map(function (_a) {
                var json = _a.json;
                return json.id;
              }),
            };
          });
        },
        create: function (resource, params) {
          return httpClient(apiUrl + "/" + resource, {
            method: "POST",
            body: JSON.stringify(params.data),
          }).then(function (_a) {
            var json = _a.json;
            return {
              data: __assign(__assign({}, params.data), { id: json.id }),
            };
          });
        },
        delete: function (resource, params) {
          return httpClient(apiUrl + "/" + resource + "/" + params.id, {
            method: "DELETE",
          }).then(function (_a) {
            var json = _a.json;
            return { data: json };
          });
        },
        // json-server doesn't handle filters on DELETE route, so we fallback to calling DELETE n times instead
        deleteMany: function (resource, params) {
          return Promise.all(
            params.ids.map(function (id) {
              return httpClient(apiUrl + "/" + resource + "/" + id, {
                method: "DELETE",
              });
            })
          ).then(function (responses) {
            return {
              data: responses.map(function (_a) {
                var json = _a.json;
                return json.id;
              }),
            };
          });
        },
      };
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2019-06-02
      • 2021-03-24
      • 1970-01-01
      • 2017-04-20
      • 2011-07-11
      • 1970-01-01
      相关资源
      最近更新 更多