DEV Community

Nathan Collins
Nathan Collins

Posted on

Building Advanced Data Tables with Sematable in React

Sematable is a powerful, Redux-based table component library for React that provides comprehensive table functionality including sorting, filtering, pagination, and selection with a focus on server-side data management. It integrates seamlessly with Redux for state management, making it ideal for complex applications requiring centralized state control. This guide walks through creating feature-rich data tables using Sematable with React and Redux, covering setup, configuration, and practical implementation patterns. This is part 17 of a series on using Sematable with React.

Prerequisites

Before you begin, ensure you have:

  • Node.js version 14.0 or higher
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) with hooks support
  • Basic understanding of React hooks and Redux
  • Redux and React-Redux installed (required dependencies)
  • Familiarity with JavaScript/TypeScript

Installation

First, install Redux and React-Redux (required dependencies):

npm install redux react-redux
Enter fullscreen mode Exit fullscreen mode

Then install Sematable:

npm install sematable
Enter fullscreen mode Exit fullscreen mode

Or install everything with yarn:

yarn add redux react-redux sematable
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add redux react-redux sematable
Enter fullscreen mode Exit fullscreen mode

Your package.json should include:

{
  "dependencies": {
    "sematable": "^3.0.0",
    "redux": "^4.0.0",
    "react-redux": "^8.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

Sematable requires Redux store setup. Configure your Redux store:

// src/store/index.js
import { createStore, combineReducers } from 'redux';
import { sematable } from 'sematable';

const rootReducer = combineReducers({
  sematable: sematable,
  // Add your other reducers here
});

const store = createStore(rootReducer);

export default store;
Enter fullscreen mode Exit fullscreen mode

Update your main entry file to include the Redux Provider:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </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 from 'react';
import { Sematable } from 'sematable';
import { tableConfig } from './tableConfig';

function DataTable() {
  const data = [
    { 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' }
  ];

  return (
    <div style={{ padding: '20px' }}>
      <h2>Employee Directory</h2>
      <Sematable
        config={tableConfig}
        data={data}
      />
    </div>
  );
}

export default DataTable;
Enter fullscreen mode Exit fullscreen mode

Create the table configuration file:

// src/tableConfig.js
import { makeTable } from 'sematable';

const tableConfig = makeTable('users', {
  primaryKey: 'id',
  columns: [
    {
      key: 'id',
      label: 'ID',
      sortable: true,
    },
    {
      key: 'name',
      label: 'Name',
      sortable: true,
      filterable: true,
    },
    {
      key: 'email',
      label: 'Email',
      sortable: true,
      filterable: true,
    },
    {
      key: 'age',
      label: 'Age',
      sortable: true,
    },
    {
      key: 'city',
      label: 'City',
      sortable: true,
      filterable: true,
    },
  ],
});

export { tableConfig };
Enter fullscreen mode Exit fullscreen mode

Understanding the Basics

Sematable uses a Redux-based architecture where:

  • makeTable: Creates a table configuration with a unique name
  • primaryKey: Unique identifier for each row
  • columns: Array of column definitions
  • Sematable: Main component that renders the table
  • Redux Store: Manages table state (sorting, filtering, pagination)

Key concepts:

  • Table Name: Unique identifier for each table instance
  • Columns: Define structure with key, label, sortable, filterable
  • Redux Integration: Table state is managed in Redux store
  • Server-side Support: Designed for server-side data loading

Here's an example with custom cell rendering:

// src/AdvancedTable.jsx
import React from 'react';
import { Sematable } from 'sematable';
import { makeTable } from 'sematable';

const productTableConfig = makeTable('products', {
  primaryKey: 'id',
  columns: [
    {
      key: 'id',
      label: 'ID',
      sortable: true,
    },
    {
      key: 'name',
      label: 'Product Name',
      sortable: true,
      filterable: true,
    },
    {
      key: 'price',
      label: 'Price',
      sortable: true,
      render: (value) => `$${value.toFixed(2)}`,
    },
    {
      key: 'stock',
      label: 'Stock',
      sortable: true,
      render: (value, row) => (
        <span style={{ 
          color: value < 10 ? 'red' : 'green',
          fontWeight: 'bold'
        }}>
          {value}
        </span>
      ),
    },
    {
      key: 'status',
      label: 'Status',
      filterable: true,
      render: (value) => (
        <span style={{
          padding: '4px 8px',
          borderRadius: '4px',
          backgroundColor: value === 'In Stock' ? '#d4edda' : '#fff3cd',
          color: value === 'In Stock' ? '#155724' : '#856404'
        }}>
          {value}
        </span>
      ),
    },
  ],
});

function AdvancedTable() {
  const data = [
    { id: 1, name: 'Laptop', price: 999.99, stock: 15, status: 'In Stock' },
    { id: 2, name: 'Mouse', price: 29.99, stock: 8, status: 'Low Stock' },
    { id: 3, name: 'Keyboard', price: 79.99, stock: 12, status: 'In Stock' }
  ];

  return (
    <div style={{ padding: '20px' }}>
      <Sematable
        config={productTableConfig}
        data={data}
      />
    </div>
  );
}

export default AdvancedTable;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive employee management system with server-side data loading:

// src/EmployeeManagement.jsx
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Sematable } from 'sematable';
import { makeTable } from 'sematable';
import { getTableState } from 'sematable';

const employeeTableConfig = makeTable('employees', {
  primaryKey: 'id',
  columns: [
    {
      key: 'id',
      label: 'ID',
      sortable: true,
      width: 80,
    },
    {
      key: 'name',
      label: 'Employee Name',
      sortable: true,
      filterable: true,
      render: (value, row) => (
        <div>
          <strong>{value}</strong>
          <div style={{ fontSize: '12px', color: '#666' }}>
            {row.email}
          </div>
        </div>
      ),
    },
    {
      key: 'department',
      label: 'Department',
      sortable: true,
      filterable: true,
      render: (value) => {
        const colors = {
          Engineering: '#dc3545',
          Marketing: '#ffc107',
          Sales: '#28a745',
          HR: '#17a2b8'
        };
        return (
          <span style={{
            padding: '4px 8px',
            borderRadius: '4px',
            backgroundColor: colors[value] || '#6c757d',
            color: 'white',
            fontSize: '12px'
          }}>
            {value}
          </span>
        );
      },
    },
    {
      key: 'salary',
      label: 'Salary',
      sortable: true,
      render: (value) => `$${value.toLocaleString()}`,
    },
    {
      key: 'startDate',
      label: 'Start Date',
      sortable: true,
      render: (value) => {
        const date = new Date(value);
        return date.toLocaleDateString('en-US');
      },
    },
    {
      key: 'status',
      label: 'Status',
      sortable: true,
      filterable: true,
      render: (value) => (
        <span style={{
          padding: '4px 8px',
          borderRadius: '4px',
          backgroundColor: value === 'Active' ? '#d4edda' : '#f8d7da',
          color: value === 'Active' ? '#155724' : '#721c24',
          fontWeight: 'bold'
        }}>
          {value}
        </span>
      ),
    },
  ],
});

function EmployeeManagement() {
  const dispatch = useDispatch();
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  const tableState = useSelector(state => 
    getTableState(state, 'employees')
  );

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const params = new URLSearchParams({
          page: (tableState?.page || 0).toString(),
          pageSize: (tableState?.pageSize || 10).toString(),
          sortBy: tableState?.sortBy || '',
          sortDirection: tableState?.sortDirection || 'asc',
          filter: tableState?.filter || '',
        });

        const response = await fetch(`/api/employees?${params}`);
        const result = await response.json();

        setData(result.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [tableState]);

  return (
    <div style={{ padding: '20px' }}>
      <h2>Employee Management</h2>
      {loading && <div>Loading...</div>}
      <Sematable
        config={employeeTableConfig}
        data={data}
        serverSide={true}
        pageSize={10}
      />
    </div>
  );
}

export default EmployeeManagement;
Enter fullscreen mode Exit fullscreen mode

This example demonstrates:

  • Server-side data loading with Redux state management
  • Custom cell rendering with React components
  • Conditional styling based on data values
  • Integration with Redux selectors
  • Pagination, sorting, and filtering state management
  • Loading states

Common Issues / Troubleshooting

  1. Table not rendering: Ensure you've set up Redux store correctly and wrapped your app with Redux Provider. Verify that the sematable reducer is included in your store.

  2. State not updating: Make sure you're using the correct table name in your configuration and when accessing state. Table names must match between config and selectors.

  3. Server-side not working: For server-side mode, ensure you're listening to table state changes and fetching data accordingly. Use getTableState selector to access current table state.

  4. Filtering not working: Verify that filterable: true is set in column definitions. Check that your filter logic matches your data structure.

  5. Redux errors: Ensure Redux DevTools are properly configured if using them. Check that all actions are properly dispatched and reducers are correctly set up.

Next Steps

Now that you understand Sematable:

  • Explore advanced Redux integration patterns
  • Implement custom actions and reducers
  • Add row selection and bulk operations
  • Learn about server-side pagination and filtering
  • Explore custom filter components
  • Add export functionality
  • Check the official repository: https://github.com/sematext/sematable
  • Look for part 18 of this series for more advanced topics

Summary

You've learned how to set up Sematable and create feature-rich data tables with Redux integration, server-side data loading, and custom rendering. The library provides a robust foundation for building enterprise-grade data management interfaces with centralized state control through Redux.

SEO Keywords

sematable React
sematable Redux table
sematable tutorial
React Redux data table
sematable installation
React table with Redux
sematable example
React server-side table
sematable setup
React data grid Redux
sematable filtering
React table component
sematable pagination
React Redux table library
sematable getting started

Top comments (0)