Issue
I have problem with pagination in react-admin, you can take a look over here: https://i.stack.imgur.com/KWw5Q.gif
the pagination always show the same records i mean all records at once.
—my backend —- :
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}`)
})
and this the dataprovider :
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 }));
}
};
and this 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;
I don’t know how to fix issues i spent two days working on it but can’t fix it.
pleas if my question not clear i will update as possible.
Solution
It seems like you are sending the required parameters to your backend (i.e. range), however, you don’t seem to be doing anything with those parameters in the backend. You have to use them to tell mongoDB that it should perform a pagination.
One way to do pagination in mongoDB is to use the skip(<number>)
(docs) and limit(<number>)
(docs) functions of the API. If you want to use those, it might make more sense that instead of sending the range
query parameter, you send a pageSize
and an offset
parameter to the backend. The pageSize
will be simply your perPage
value, the offset
would be computed by multiplying page
with perPage
.
Then, in your backend you will need to retrieve those parameters from the query object. You can do so by
const { offset, pageSize } = req.query;
However, be aware that those parameters will be string values, so you want to parse them to numbers before passing them as parameters to the skip
and limit
function.