Reputation: 590
I'm trying to implement a table in my React app with MaterialUI Table. I'm using Table Pagination component and it seems that the page change handling is not working properly, the list doesn't update when changing page. What could I do? Thanks in advance for any help. It'll be appreciated.
This is my code:
const UserList = () => {
const classes = useStyles();
const { isLoading, error, sendRequest, clearError } = useHttpClient();
const [usersList, setUsersList] = useState([]);
useEffect(() => {
const fetchSettings = async () => {
try {
const responseData = await sendRequest(
process.env.REACT_APP_BACKEND_URL + '/api/users'
);
setUsersList(responseData)
} catch (err) { }
};
fetchSettings();
}, [sendRequest]);
return (
<React.Fragment>
<ErrorModal error={error} onClear={clearError} />
{usersList.users ? (
<div className={classes.root}>
<UsersToolbar />
<div className={classes.content}>
<UsersTable users={usersList.users} />
</div>
</div>
) : (
<div>
{isLoading ? (
<label className={classes.paragraph}>Users list is loading, please wait...</label>
) : (
<label className={classes.paragraph}>Failed to load users. Server could be offline.</label>
)}
{isLoading && <LoadingLine />}
</div>
)}
</React.Fragment>
);
};
export default UserList;
... ...
const UsersTable = props => {
const { className, users, ...rest } = props;
const classes = useStyles();
const [selectedUsers, setSelectedUsers] = useState([]);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [page, setPage] = useState(0);
const handleSelectAll = event => {
const { users } = props;
let selectedUsers;
if (event.target.checked) {
selectedUsers = users.map(user => user.id);
} else {
selectedUsers = [];
}
setSelectedUsers(selectedUsers);
};
const handleSelectOne = (event, id) => {
const selectedIndex = selectedUsers.indexOf(id);
let newSelectedUsers = [];
if (selectedIndex === -1) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers, id);
} else if (selectedIndex === 0) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers.slice(1));
} else if (selectedIndex === selectedUsers.length - 1) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers.slice(0, -1));
} else if (selectedIndex > 0) {
newSelectedUsers = newSelectedUsers.concat(
selectedUsers.slice(0, selectedIndex),
selectedUsers.slice(selectedIndex + 1)
);
}
setSelectedUsers(newSelectedUsers);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
const handleRowsPerPageChange = event => {
setRowsPerPage(event.target.value);
};
return (
<Card
{...rest}
className={clsx(classes.root, className)}
>
<CardContent className={classes.content}>
<PerfectScrollbar>
<div className={classes.inner}>
<Table>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
style={{ color: 'orange' }}
checked={selectedUsers.length === users.length}
indeterminate={
selectedUsers.length > 0 &&
selectedUsers.length < users.length
}
onChange={handleSelectAll}
/>
</TableCell>
<TableCell className={classes.tableCell}>Name</TableCell>
<TableCell className={classes.tableCell}>Email</TableCell>
<TableCell className={classes.tableCell}>Administrator</TableCell>
<TableCell className={classes.tableCell}>Registration Date</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.slice(0, rowsPerPage).map(user => (
<TableRow
className={classes.tableRow}
hover
key={user.id}
selected={selectedUsers.indexOf(user.id) !== -1}
>
<TableCell padding="checkbox">
<Checkbox
style={{ color: 'orange' }}
checked={selectedUsers.indexOf(user.id) !== -1}
onChange={event => handleSelectOne(event, user.id)}
value="true"
/>
</TableCell>
<TableCell>
<div className={classes.nameContainer}>
<Avatar
className={classes.avatar}
src={user.avatarUrl}
>
{
(user.username)
.replace(/\s+/, ' ')
.split(' ')
.slice(0, 2)
.map(v => v && v[0].toUpperCase())
.join('')
}
</Avatar>
<Typography style={{ color: 'orange' }} variant="body1">{user.username}</Typography>
</div>
</TableCell>
<TableCell style={{ color: 'white' }} >{user.email}</TableCell>
<TableCell style={{ color: 'white' }} >{user.isAdmin.toString()}</TableCell>
<TableCell style={{ color: 'white' }}>
{moment(user.createdAt).format('YYYY-MM-DD')}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</PerfectScrollbar>
</CardContent>
<CardActions className={classes.actions}>
<TablePagination
style={{ color: 'white' }}
component="div"
count={users.length}
onChangePage={handlePageChange}
onChangeRowsPerPage={handleRowsPerPageChange}
page={page}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[5, 10, 25]}
/>
</CardActions>
</Card>
);
};
UsersTable.propTypes = {
className: PropTypes.string,
users: PropTypes.array.isRequired
};
export default UsersTable;
Upvotes: 2
Views: 5927
Reputation: 5288
The problem is when you do
users.slice(0, rowsPerPage).map(user => ...
you're looping on the same array of users, even your page
state updates.
Change that line to
users.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map(user => ...
More about slice
function here.
The code above is also implemented on material-ui's table examples.
--
Upvotes: 4