Reputation: 6447
I am using Material-UI Data-Grid, and I'm running a tutorial grid for server-side data access. This is written in React, and I'm having a problem that the loading circle is permanently spinning. I set a breakpoint in React.useEffect
and I see it getting hit over and over and over. handlePageChange
doesn't seem to be participating in the infinite loop.
Thinking about this a little, I feel that the state is changing which triggers the whole thing to execute again, hence the loop. What is the condition supposed to be to stop the thing?
import * as React from 'react';
import { DataGrid } from '@material-ui/data-grid';
function loadServerRows(page, data) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data.rows.slice(page * 5, (page + 1) * 5));
}, Math.random() * 500 + 100); // simulate network latency
});
}
export default function App() {
const data = {
rows: [
{ id: 1, col1: 'Hello', col2: 'World' },
{ id: 2, col1: 'XGrid', col2: 'is Awesome' },
{ id: 3, col1: 'Material-UI', col2: 'is Amazing' },
],
columns: [
{ field: 'col1', headerName: 'Column 1', width: 150 },
{ field: 'col2', headerName: 'Column 2', width: 150 },
],
rowLength: 100,
maxColumns: 6
}
const [page, setPage] = React.useState(0);
const [rows, setRows] = React.useState([]);
const [loading, setLoading] = React.useState(false);
const handlePageChange = (params) => {
setPage(params.page);
};
React.useEffect(() => {
let active = true;
(async () => {
setLoading(true);
const newRows = await loadServerRows(page, data);
if (!active) {
return;
}
setRows(newRows);
setLoading(false);
})();
return () => {
active = false;
};
}, [page, data]);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
columns={data.columns}
pagination
pageSize={5}
rowCount={100}
paginationMode="server"
onPageChange={handlePageChange}
loading={loading}
/>
</div>
);
}
Upvotes: 3
Views: 17156
Reputation: 20118
In your code data changes on each render. As an option, you can store data with useRef (or just make it global moving out of component):
import React from 'react'
import { DataGrid } from '@material-ui/data-grid'
function loadServerRows(page, data) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data.rows.slice(page * 5, (page + 1) * 5))
}, Math.random() * 500 + 100) // simulate network latency
})
}
function App() {
const data = React.useRef({
rows: [
{ id: 1, col1: 'Hello', col2: 'World' },
{ id: 2, col1: 'XGrid', col2: 'is Awesome' },
{ id: 3, col1: 'Material-UI', col2: 'is Amazing' },
],
columns: [
{ field: 'col1', headerName: 'Column 1', width: 150 },
{ field: 'col2', headerName: 'Column 2', width: 150 },
],
rowLength: 100,
maxColumns: 6
})
const [page, setPage] = React.useState(0)
const [rows, setRows] = React.useState([])
const [loading, setLoading] = React.useState(false)
const handlePageChange = (params) => {
setPage(params.page)
}
React.useEffect(() => {
let active = true;
(async () => {
setLoading(true)
const newRows = await loadServerRows(page, data.current)
if (!active) {
return
}
setRows(newRows)
setLoading(false)
})()
return () => {
active = false
}
}, [page, data])
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
columns={data.current.columns}
pagination
pageSize={5}
rowCount={100}
paginationMode="server"
onPageChange={handlePageChange}
loading={loading}
/>
</div>
)
}
Upvotes: 5