React | Table

by matox

HTML

<div id="root"></div>

CSS

/* Center tables for demo */

.tableSearch {
  display: flex;
  justify-content: center;
  margin: 1rem 0;
}

table {
  margin: 0 auto;
}

/* Default Table Style */
table {
  color: #333;
  background: white;
  border: 1px solid grey;
  font-size: 12pt;
  border-collapse: collapse;
}
table thead th,
table tfoot th {
  color: #777;
  background: rgba(0,0,0,.1);
}
table caption {
  padding:.5em;
}
table th,
table td {
  padding: .5em;
  border: 1px solid lightgrey;
}
/* Zebra Table Style */
[data-table-theme*=zebra] tbody tr:nth-of-type(odd) {
  background: rgba(0,0,0,.05);
}
[data-table-theme*=zebra][data-table-theme*=dark] tbody tr:nth-of-type(odd) {
  background: rgba(255,255,255,.05);
}
/* Dark Style */
[data-table-theme*=dark] {
  color: #ddd;
  background: #333;
  font-size: 12pt;
  border-collapse: collapse;
}
[data-table-theme*=dark] thead th,
[data-table-theme*=dark] tfoot th {
  color: #aaa;
  background: rgba(0255,255,255,.15);
}
[data-table-theme*=dark] caption {
  padding:.5em;
}
[data-table-theme*=dark] th,
[data-table-theme*=dark] td {
  padding: .5em;
  border: 1px solid grey;
}

React

function Table(props) {
	const [table, setTable] = React.useState([]);
  const [searchQuery, setSearchQuery] = React.useState();
  const [tableSort, setTableSort] = React.useState({field: 'id', asc: true});

	React.useEffect(() => {
  	async function fetchData() {
      /* const response = await fetch('https://table.free.beeceptor.com/data'); */
      
      const response = {
      	status: 200,
        text: () => new Promise((resolve, reject) => {
          resolve('[{"id":"627a9d0f7e286a09bf041aa1","isActive":true,"age":28,"name":"Horton Franklin","company":"BARKARAMA"},{"id":"627a9d0fc04ffcab2f575f42","isActive":true,"age":20,"name":"Lee Landry","company":"XANIDE"},{"id":"627a9d0f3f69fd8b7bf14063","isActive":false,"age":36,"name":"Carey Mcdowell","company":"MOBILDATA"},{"id":"627a9d0f4c430e638ecb8779","isActive":true,"age":22,"name":"Karina Patton","company":"SONGLINES"},{"id":"627a9d0f273d7cc7aaac61c5","isActive":true,"age":26,"name":"Dora Leach","company":"BRAINQUIL"},{"id":"627a9d0f39fecf79c80005c2","isActive":true,"age":37,"name":"Norton Christensen","company":"CANDECOR"}]')
        })
      };
      
      if (response.status === 200) {
      	const json = JSON.parse(await response.text());
        setTable(json);
      }
    }
    
  	fetchData();
  }, []);
  
  const sortTable = (a, b) => {
    const {field, asc} = tableSort;
    const [fa, fb] = [a[field], b[field]].map(String);
  	return ((fa < fb) ? 1 : -1) * (asc ? 1 : -1);
  }
  
  const tableRows = table
    .filter(row => {
      if (searchQuery == null) {
        return row;
      }
      
      const obj = JSON.stringify(row).toLowerCase();
      const q = searchQuery.toLowerCase();
      return obj.includes(q) ? row : null;
    })
    .sort(sortTable)
    .map((row) => 
      <TableRow
        key={row.id}
        row={row}
       />
     );
   
   const handleSearch = (query) => setSearchQuery(query);
   const handleSort = (field) => {
   	const state = tableSort;
   	setTableSort({
   ...