如何处理从后端(nodejs)返回的数据以使分页在 react-admin 中工作

How to handle the data returned from the backend (nodejs) to make pagination work in react-admin

我在 react-admin 中的分页有问题,你可以看这里:https://i.stack.imgur.com/KWw5Q.gif
分页总是显示相同的记录,我的意思是一次显示所有记录。

---我的后端---- :

const express = require('express')
const app = express()
const port = 5000
var MongoClient = require("mongodb").MongoClient;
const { ObjectId } = require("mongodb"); // or ObjectID
var url = "mongodb://localhost:27017/storedz";
var db;
var storedz;


app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Origin", req.header("Origin"));
  res.header("Access-Control-Allow-Credentials", true);
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );

  res.header("Access-Control-Expose-Headers", "Content-Range");
  res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
  next();
});



MongoClient.connect(url, function (err, database) {
    if (err) throw err;
    db = database;
    storedz = db.db("storedz");
  });



app.get('/Products',(req, res) => {
  storedz
    .collection("products")
    .find({})
    .toArray((err, result) => {
      if (err) {
        return res.header(400).json("something went wrong");
      }
      res.header("Content-Range", `Products 1-${result.length}/${result.length}`);
      console.log(result.length)
      res.json(result);
    });

  })

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

这是数据提供者:

import { fetchUtils } from 'react-admin';
import { stringify } from 'query-string';

const apiUrl = 'http://localhost:5000';
const httpClient = fetchUtils.fetchJson;

export default {
    getList: (resource, params) => {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify(params.filter),
        };
        const url = `${apiUrl}/${resource}?${stringify(query)}`;
     
        return httpClient(url).then(({ headers, json }) => ({
            data: json.map((resource)=>({...resource, id:resource._id})),
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    },

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

    getMany: (resource, params) => {
        const query = {
            filter: JSON.stringify({ id: params.ids }),
        };
        const url = `${apiUrl}/${resource}?${stringify(query)}`;
        return httpClient(url).then(({ json }) => ({
            data: json.map(resource => ({ ...resource, id: resource._id }) )
             }));
    },

    getManyReference: (resource, params) => {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify({
                ...params.filter,
                [params.target]: params.id,
            }),
        };
        const url = `${apiUrl}/${resource}?${stringify(query)}`;

        return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    },

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

    updateMany: (resource, params) => {
        const query = {
            filter: JSON.stringify({ id: params.ids}),
        };
        return httpClient(`${apiUrl}/${resource}?${stringify(query)}`, {
            method: 'PUT',
            body: JSON.stringify(params.data),
        }).then(({ json }) => ({ 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: (resource, params) => {
        const query = {
            filter: JSON.stringify({ id: params.ids}),
        };
        return httpClient(`${apiUrl}/${resource}?${stringify(query)}`, {
            method: 'DELETE',
        }).then(({ json }) => ({ data: json }));
    }
};

和这个 App.js:

import * as React from "react";
import { Admin, Resource  } from 'react-admin';
import  dataProvider  from './DataProvider'
import { Products } from "./Products";
const App=()=> {

  return (
    <div className="App">
<Admin  dataProvider={dataProvider}>
<Resource name='Products' list={Products} />
  </Admin>
    </div>
  );
}

export default App;

我不知道如何解决我花了两天时间解决的问题,但无法解决。
如果我的问题不清楚,我会尽可能更新。

您似乎正在向后端发送所需的参数(即范围),但是,您似乎没有在后端对这些参数执行任何操作。您必须使用它们来告诉 mongoDB 它应该执行分页。

在 mongoDB 中进行分页的一种方法是使用 API 的 skip(<number>) (docs) and limit(<number>) (docs) 函数。如果你想使用它们,而不是发送 range 查询参数,你发送一个 pageSize 和一个 offset 参数到后端可能更有意义。 pageSize 将只是您的 perPage 值,offset 将通过 page 乘以 perPage 来计算。

然后,您需要在后端从查询对象中检索这些参数。您可以通过

const { offset, pageSize } = req.query;

但是,请注意这些参数将是字符串值,因此您希望在将它们作为参数传递给 skiplimit 函数之前将它们解析为数字。