DEV Community

Nathan Collins
Nathan Collins

Posted on

Advanced Data Table Implementation with React Table Library

React Table Library is a powerful, modular table component library for React that provides a flexible architecture for building complex data tables. It offers features like sorting, filtering, pagination, selection, and tree structures with a plugin-based system that allows extensive customization. This guide walks through implementing advanced table features using React Table Library with React, covering complex data manipulation, custom plugins, and enterprise-grade implementations. This is part 15 of a series on using React Table Library with React.

Prerequisites

Before you begin, ensure you have:

  • Node.js version 16.0 or higher
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) with hooks support
  • Advanced understanding of React hooks, context API, and state management
  • Familiarity with TypeScript (highly recommended)
  • Knowledge of functional programming and plugin architectures

Installation

Install React Table Library core package:

npm install @table-library/react-table-library
Enter fullscreen mode Exit fullscreen mode

For additional features, install specific plugins:

npm install @table-library/react-table-library @table-library/react-table-library/theme @table-library/react-table-library/sort @table-library/react-table-library/filter @table-library/react-table-library/pagination
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add @table-library/react-table-library @table-library/react-table-library/theme @table-library/react-table-library/sort @table-library/react-table-library/filter @table-library/react-table-library/pagination
Enter fullscreen mode Exit fullscreen mode

Your package.json should include:

{
  "dependencies": {
    "@table-library/react-table-library": "^4.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

React Table Library requires minimal setup. Import the necessary components and themes:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

First Example / Basic Usage

Let's create a basic table component. Create src/DataTable.jsx:

// src/DataTable.jsx
import React, { useMemo } from 'react';
import {
  Table,
  Header,
  HeaderRow,
  HeaderCell,
  Body,
  Row,
  Cell,
} from '@table-library/react-table-library/table';
import { useTheme } from '@table-library/react-table-library/theme';
import { DEFAULT_THEME } from '@table-library/react-table-library/theme';

function DataTable() {
  const data = {
    nodes: [
      { id: '1', name: 'John Doe', email: 'john@example.com', age: 28, city: 'New York' },
      { id: '2', name: 'Jane Smith', email: 'jane@example.com', age: 32, city: 'London' },
      { id: '3', name: 'Bob Johnson', email: 'bob@example.com', age: 45, city: 'Paris' },
      { id: '4', name: 'Alice Williams', email: 'alice@example.com', age: 29, city: 'Tokyo' }
    ]
  };

  const theme = useTheme(DEFAULT_THEME);

  return (
    <div style={{ padding: '20px' }}>
      <h2>Employee Directory</h2>
      <Table data={data} theme={theme}>
        {(tableList) => (
          <>
            <Header>
              <HeaderRow>
                <HeaderCell>ID</HeaderRow>
                <HeaderCell>Name</HeaderRow>
                <HeaderCell>Email</HeaderRow>
                <HeaderCell>Age</HeaderRow>
                <HeaderCell>City</HeaderRow>
              </HeaderRow>
            </Header>
            <Body>
              {tableList.map((item) => (
                <Row key={item.id} item={item}>
                  <Cell>{item.id}</Cell>
                  <Cell>{item.name}</Cell>
                  <Cell>{item.email}</Cell>
                  <Cell>{item.age}</Cell>
                  <Cell>{item.city}</Cell>
                </Row>
              ))}
            </Body>
          </>
        )}
      </Table>
    </div>
  );
}

export default DataTable;
Enter fullscreen mode Exit fullscreen mode

Understanding the Basics

React Table Library uses a plugin-based architecture where:

  • Table: Main component that wraps the table structure
  • Data Structure: Uses { nodes: [...] } format
  • Render Props: Table uses render props pattern for rendering
  • Plugins: Enable features like sorting, filtering, pagination
  • Theme: Customizable theming system

Key concepts for advanced usage:

  • Nodes: Data items in the nodes array
  • Plugins: Modular features (sort, filter, pagination, etc.)
  • Theme: Styling system with built-in themes or custom themes
  • Render Props: Table component uses render props for flexible rendering

Here's an example with sorting:

// src/SortableTable.jsx
import React, { useMemo } from 'react';
import {
  Table,
  Header,
  HeaderRow,
  HeaderCell,
  Body,
  Row,
  Cell,
} from '@table-library/react-table-library/table';
import { useSort } from '@table-library/react-table-library/sort';
import { useTheme } from '@table-library/react-table-library/theme';
import { DEFAULT_THEME } from '@table-library/react-table-library/theme';

function SortableTable() {
  const data = {
    nodes: [
      { id: '1', name: 'Laptop', category: 'Electronics', price: 999.99, stock: 15 },
      { id: '2', name: 'Mouse', category: 'Electronics', price: 29.99, stock: 8 },
      { id: '3', name: 'Keyboard', category: 'Electronics', price: 79.99, stock: 12 }
    ]
  };

  const theme = useTheme(DEFAULT_THEME);
  const sort = useSort(
    data,
    {
      onChange: onSortChange,
    },
    {
      sortFns: {
        PRICE: (array) => array.sort((a, b) => a.price - b.price),
        STOCK: (array) => array.sort((a, b) => a.stock - b.stock),
      },
    }
  );

  function onSortChange(action, state) {
    console.log(action, state);
  }

  return (
    <Table data={data} theme={theme} sort={sort}>
      {(tableList) => (
        <>
          <Header>
            <HeaderRow>
              <HeaderCell sort={{ sortKey: 'NAME' }}>Name</HeaderRow>
              <HeaderCell sort={{ sortKey: 'CATEGORY' }}>Category</HeaderRow>
              <HeaderCell sort={{ sortKey: 'PRICE' }}>Price</HeaderRow>
              <HeaderCell sort={{ sortKey: 'STOCK' }}>Stock</HeaderRow>
            </HeaderRow>
          </Header>
          <Body>
            {tableList.map((item) => (
              <Row key={item.id} item={item}>
                <Cell>{item.name}</Cell>
                <Cell>{item.category}</Cell>
                <Cell>${item.price.toFixed(2)}</Cell>
                <Cell>{item.stock}</Cell>
              </Row>
            ))}
          </Body>
        </>
      )}
    </Table>
  );
}

export default SortableTable;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive admin dashboard with sorting, filtering, pagination, and selection:

// src/AdminDashboard.jsx
import React, { useState, useMemo } from 'react';
import {
  Table,
  Header,
  HeaderRow,
  HeaderCell,
  Body,
  Row,
  Cell,
} from '@table-library/react-table-library/table';
import { useSort } from '@table-library/react-table-library/sort';
import { useFilter } from '@table-library/react-table-library/filter';
import { usePagination } from '@table-library/react-table-library/pagination';
import { useRowSelect } from '@table-library/react-table-library/select';
import { useTheme } from '@table-library/react-table-library/theme';
import { DEFAULT_THEME } from '@table-library/react-table-library/theme';

function AdminDashboard() {
  const [data, setData] = useState({
    nodes: [
      { 
        id: '1', 
        name: 'Sarah Johnson', 
        email: 'sarah@example.com',
        department: 'Engineering', 
        salary: 95000, 
        startDate: '2020-01-15',
        status: 'Active'
      },
      { 
        id: '2', 
        name: 'Michael Chen', 
        email: 'michael@example.com',
        department: 'Marketing', 
        salary: 75000, 
        startDate: '2019-06-20',
        status: 'Active'
      },
      { 
        id: '3', 
        name: 'Emily Davis', 
        email: 'emily@example.com',
        department: 'Sales', 
        salary: 65000, 
        startDate: '2021-03-10',
        status: 'Active'
      },
      { 
        id: '4', 
        name: 'David Wilson', 
        email: 'david@example.com',
        department: 'Engineering', 
        salary: 110000, 
        startDate: '2018-09-05',
        status: 'Active'
      },
      { 
        id: '5', 
        name: 'Lisa Anderson', 
        email: 'lisa@example.com',
        department: 'HR', 
        salary: 70000, 
        startDate: '2022-01-08',
        status: 'Active'
      }
    ]
  });

  const theme = useTheme(DEFAULT_THEME);

  // Sorting
  const sort = useSort(
    data,
    {
      onChange: onSortChange,
    },
    {
      sortFns: {
        SALARY: (array) => array.sort((a, b) => a.salary - b.salary),
        START_DATE: (array) => array.sort((a, b) => 
          new Date(a.startDate) - new Date(b.startDate)
        ),
      },
    }
  );

  // Filtering
  const filter = useFilter(
    data,
    {
      onChange: onFilterChange,
    },
    {
      isServerSide: false,
    }
  );

  // Pagination
  const pagination = usePagination(data, {
    state: {
      page: 0,
      size: 10,
    },
    onChange: onPaginationChange,
  });

  // Row Selection
  const select = useRowSelect(data, {
    onChange: onSelectChange,
  });

  function onSortChange(action, state) {
    console.log('Sort changed:', state);
  }

  function onFilterChange(action, state) {
    console.log('Filter changed:', state);
  }

  function onPaginationChange(action, state) {
    console.log('Pagination changed:', state);
  }

  function onSelectChange(action, state) {
    console.log('Selection changed:', state);
  }

  const handleSearch = (value) => {
    filter.fns.onFilterChange({
      type: 'FILTER',
      payload: {
        name: value,
      },
    });
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>Admin Dashboard</h2>

      {/* Search */}
      <div style={{ marginBottom: '16px' }}>
        <input
          type="text"
          placeholder="Search employees..."
          onChange={(e) => handleSearch(e.target.value)}
          style={{
            padding: '8px',
            width: '300px',
            border: '1px solid #ddd',
            borderRadius: '4px'
          }}
        />
      </div>

      {/* Table */}
      <Table 
        data={data} 
        theme={theme} 
        sort={sort}
        filter={filter}
        pagination={pagination}
        select={select}
      >
        {(tableList) => (
          <>
            <Header>
              <HeaderRow>
                <HeaderCell>
                  <input
                    type="checkbox"
                    checked={select.state.all}
                    onChange={select.fns.onToggleAll}
                  />
                </HeaderRow>
                <HeaderCell sort={{ sortKey: 'NAME' }}>Name</HeaderRow>
                <HeaderCell sort={{ sortKey: 'EMAIL' }}>Email</HeaderRow>
                <HeaderCell sort={{ sortKey: 'DEPARTMENT' }}>Department</HeaderRow>
                <HeaderCell sort={{ sortKey: 'SALARY' }}>Salary</HeaderRow>
                <HeaderCell sort={{ sortKey: 'START_DATE' }}>Start Date</HeaderRow>
                <HeaderCell sort={{ sortKey: 'STATUS' }}>Status</HeaderRow>
              </HeaderRow>
            </Header>
            <Body>
              {tableList.map((item) => (
                <Row 
                  key={item.id} 
                  item={item}
                  style={{
                    backgroundColor: select.state.ids.includes(item.id) 
                      ? '#e3f2fd' 
                      : 'white'
                  }}
                >
                  <Cell>
                    <input
                      type="checkbox"
                      checked={select.state.ids.includes(item.id)}
                      onChange={() => select.fns.onToggleById(item.id)}
                    />
                  </Cell>
                  <Cell>
                    <div>
                      <strong>{item.name}</strong>
                      <div style={{ fontSize: '12px', color: '#666' }}>
                        {item.email}
                      </div>
                    </div>
                  </Cell>
                  <Cell>{item.email}</Cell>
                  <Cell>
                    <span style={{
                      padding: '4px 8px',
                      borderRadius: '4px',
                      backgroundColor: '#dc3545',
                      color: 'white',
                      fontSize: '12px'
                    }}>
                      {item.department}
                    </span>
                  </Cell>
                  <Cell>${item.salary.toLocaleString()}</Cell>
                  <Cell>
                    {new Date(item.startDate).toLocaleDateString('en-US')}
                  </Cell>
                  <Cell>
                    <span style={{
                      padding: '4px 8px',
                      borderRadius: '4px',
                      backgroundColor: item.status === 'Active' ? '#d4edda' : '#f8d7da',
                      color: item.status === 'Active' ? '#155724' : '#721c24',
                      fontWeight: 'bold'
                    }}>
                      {item.status}
                    </span>
                  </Cell>
                </Row>
              ))}
            </Body>
          </>
        )}
      </Table>

      {/* Pagination Controls */}
      <div style={{ marginTop: '16px', display: 'flex', gap: '8px', alignItems: 'center' }}>
        <button
          onClick={() => pagination.fns.onSetPage(0)}
          disabled={pagination.state.page === 0}
          style={{ padding: '8px 16px', cursor: 'pointer' }}
        >
          {'<<'}
        </button>
        <button
          onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
          disabled={pagination.state.page === 0}
          style={{ padding: '8px 16px', cursor: 'pointer' }}
        >
          {'<'}
        </button>
        <span>
          Page {pagination.state.page + 1} of {pagination.state.getTotalPages(data.nodes)}
        </span>
        <button
          onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
          disabled={pagination.state.page + 1 >= pagination.state.getTotalPages(data.nodes)}
          style={{ padding: '8px 16px', cursor: 'pointer' }}
        >
          {'>'}
        </button>
        <button
          onClick={() => pagination.fns.onSetPage(pagination.state.getTotalPages(data.nodes) - 1)}
          disabled={pagination.state.page + 1 >= pagination.state.getTotalPages(data.nodes)}
          style={{ padding: '8px 16px', cursor: 'pointer' }}
        >
          {'>>'}
        </button>
      </div>
    </div>
  );
}

export default AdminDashboard;
Enter fullscreen mode Exit fullscreen mode

This advanced example demonstrates:

  • Multiple plugins working together (sort, filter, pagination, select)
  • Custom cell rendering with React components
  • Row selection with checkboxes
  • Global search/filtering
  • Custom sorting functions
  • Pagination controls
  • Conditional styling
  • Status badges and department chips

Common Issues / Troubleshooting

  1. Table not rendering: Ensure your data structure uses { nodes: [...] } format. The Table component expects this specific structure.

  2. Plugins not working: Make sure you've installed the specific plugin packages and imported them correctly. Each plugin needs to be passed to the Table component.

  3. Sorting not working: Verify that you've included the sort prop from useSort hook and set sortKey in HeaderCell components.

  4. Filtering issues: Ensure you've set up the filter plugin correctly and are calling filter functions properly. Check that your filter logic matches your data structure.

  5. TypeScript errors: React Table Library has TypeScript support. Define your data types and ensure your node structure matches the expected interface.

Next Steps

Now that you've mastered React Table Library:

  • Explore tree table features for hierarchical data
  • Implement custom plugins and extensions
  • Add server-side data loading
  • Learn about column resizing and reordering
  • Explore advanced theming and customization
  • Add export functionality
  • Check the official repository: https://github.com/table-library/react-table-library
  • Look for part 16 of this series for more advanced topics

Summary

You've learned how to implement advanced data table features with React Table Library, including sorting, filtering, pagination, and row selection using a plugin-based architecture. The library provides extensive flexibility for building enterprise-grade data management interfaces with modular, composable features.

SEO Keywords

react-table-library
React Table Library tutorial
react-table-library advanced
React data table plugin
react-table-library installation
React table component
react-table-library example
React data grid
react-table-library setup
React interactive table
react-table-library sorting
React enterprise table
react-table-library filtering
React table library pagination
react-table-library selection

Top comments (0)