Categories
Material UI

Material UI — Virtualized Lists and Tables

Spread the love

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add lists with pinned headings, virtualized lists, and tables with Material UI.

Pinned Subheader List

We can use CSS to make the subheader pinned to the top of the screen until it’s pushed off by the next subheader.

For example, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import ListSubheader from "@material-ui/core/ListSubheader";

const useStyles = makeStyles(theme => ({
  root: {
    width: "100%",
    maxWidth: 360,
    backgroundColor: theme.palette.background.paper,
    position: "relative",
    overflow: "auto",
    maxHeight: 300
  },
  listSection: {
    backgroundColor: "inherit"
  },
  ul: {
    backgroundColor: "inherit",
    padding: 0
  }
}));

export default function App() {
  const classes = useStyles();

  return (
    <List className={classes.root} subheader={<li />}>
      {Array(10)
        .fill()
        .map((s, sectionId) => (
          <li key={`section-${sectionId}`} className={classes.listSection}>
            <ul className={classes.ul}>
              <ListSubheader>{`I'm sticky ${sectionId}`}</ListSubheader>
              {[0, 1, 2].map(item => (
                <ListItem key={`item-${sectionId}-${item}`}>
                  <ListItemText primary={`Item ${item}`} />
                </ListItem>
              ))}
            </ul>
          </li>
        ))}
    </List>
  );
}

We have the makeStyles function to set the position of the root to relative .

Also, we set a maxHeight so that it will scroll when the content overflows the list.

This way, we set the subheader to stay pinned.

Inset List

We can make list items that have no icon with text that aligns with the ones with icons.

For example, we can write:

import React from "react";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import StarIcon from "@material-ui/icons/Star";

export default function App() {
  return (
    <List aria-label="contacts">
      <ListItem button>
        <ListItemIcon>
          <StarIcon />
        </ListItemIcon>
        <ListItemText primary="james smith" />
      </ListItem>
      <ListItem button>
        <ListItemText inset primary="mary jane" />
      </ListItem>
    </List>
  );
}

We added the inset prop to make the text in the 2nd list item aligns with the text on the first.

Virtualized List

If we have a list with lots of items, then we’ve to make a virtualized list.

To do that, we can write:

import React from "react";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import { FixedSizeList } from "react-window";

function renderRow(props) {
  const { index, style } = props;

  return (
    <ListItem button style={style} key={index}>
      <ListItemText primary={`Item ${index + 1}`} />
    </ListItem>
  );
}

export default function App() {
  return (
    <FixedSizeList height={300} width={300} itemSize={40} itemCount={300}>
      {renderRow}
    </FixedSizeList>
  );
}

to create a virtualized list with react-window.

We have the renderRow to render a table row.

And we used the FixedSizedList instead of a regular List .

itemCount sets the item count.

itemSize has the size of an item.

The height and width are the height and width of the list.

Table

Material UI comes with a table component to let us display data in a table.

To create a simple one, we can write the following:

import React from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";

function createData(firstName, lastName, age) {
  return { firstName, lastName, age };
}

const rows = [
  createData("james", "smith", 20),
  createData("mary", "jones", 30),
  createData("may", "wong", 30)
];

export default function App() {
  return (
    <TableContainer component={Paper}>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>first name</TableCell>
            <TableCell>last name</TableCell>
            <TableCell align="right">age</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map(row => (
            <TableRow key={row.name}>
              <TableCell component="th" scope="row">
                {row.firstName}
              </TableCell>
              <TableCell>{row.lastName}</TableCell>
              <TableCell align="right">{row.age}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

We created a table with the TableContainer , Table , TableHead , TableRow and TableCell components.

TableContainer has the container.

Tabke has the table itself.

TableHead holds the headings.

TableRow has the rows.

TableCell has the cells.

We can set the align prop of a cell to right to make the content align to the right.

Also, we can set the component prop to display as th if we wish.

The scope is set to the row to indicate that the cell is for a row and we get different cell formatting than headings.

Conclusion

We can make virtualized lists if our list has lots of items.

List headings can be pinned.

Table components are part of the core Material UI package.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *