Flavio Del Grosso
Flavio Del Grosso

Reputation: 590

MaterialUI Table Pagination doesn't update list on page change

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

Answers (1)

bertdida
bertdida

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.

--

Edit modest-dijkstra-mu5ub

Upvotes: 4

Related Questions