DEV Community

Michael Turner
Michael Turner

Posted on

Advanced Data Management with GigaTables React: Building Enterprise-Grade Tables

GigaTables React is a powerful, feature-rich table component library for React that provides advanced data management capabilities including server-side processing, real-time updates, complex filtering, and custom rendering. It's designed for enterprise applications that require sophisticated data manipulation and presentation. This guide walks through implementing advanced table features using GigaTables React, covering server-side data loading, custom components, and complex interactions. This is part 3 of a series on using GigaTables React 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 async operations and API integration
  • Knowledge of TypeScript (optional but recommended)

Installation

Install GigaTables React and its dependencies:

npm install gigatables-react
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add gigatables-react
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add gigatables-react
Enter fullscreen mode Exit fullscreen mode

For TypeScript support, you may also need type definitions:

npm install --save-dev @types/react @types/react-dom
Enter fullscreen mode Exit fullscreen mode

Your package.json should include:

{
  "dependencies": {
    "gigatables-react": "^3.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

GigaTables React requires minimal setup. Create a configuration file for table settings:

// src/config/tableConfig.js
export const defaultTableConfig = {
  ajax: {
    url: '/api/data',
    type: 'GET'
  },
  columns: [],
  pagination: {
    enabled: true,
    pageSize: 10,
    position: 'bottom'
  },
  sorting: {
    enabled: true,
    multiColumn: true
  },
  filtering: {
    enabled: true,
    global: true
  }
};
Enter fullscreen mode Exit fullscreen mode

First Example / Basic Usage

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

// src/components/DataTable.jsx
import React, { useState, useEffect } from 'react';
import { GigaTables } from 'gigatables-react';

function DataTable() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Simulate API call
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await fetch('/api/users');
        const result = await response.json();
        setData(result);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  const columns = [
    {
      name: 'id',
      title: 'ID',
      sortable: true,
      width: 80
    },
    {
      name: 'name',
      title: 'Name',
      sortable: true,
      filterable: true
    },
    {
      name: 'email',
      title: 'Email',
      sortable: true,
      filterable: true
    },
    {
      name: 'role',
      title: 'Role',
      sortable: true,
      filterable: true
    },
    {
      name: 'status',
      title: 'Status',
      sortable: true,
      render: (value) => (
        <span style={{ 
          color: value === 'active' ? 'green' : 'red',
          fontWeight: 'bold'
        }}>
          {value}
        </span>
      )
    }
  ];

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div style={{ padding: '20px' }}>
      <h2>User Management Table</h2>
      <GigaTables
        data={data}
        columns={columns}
        pagination={{
          enabled: true,
          pageSize: 10
        }}
        sorting={{
          enabled: true
        }}
        filtering={{
          enabled: true
        }}
      />
    </div>
  );
}

export default DataTable;
Enter fullscreen mode Exit fullscreen mode

Understanding the Basics

GigaTables React uses a column-based configuration system where each column defines:

  • name: Property key in your data objects
  • title: Display header text
  • sortable: Enable sorting for the column
  • filterable: Enable filtering
  • render: Custom render function for cell content
  • width: Fixed column width

Key concepts for advanced usage:

  • Server-side processing: Load data asynchronously from APIs
  • Custom renderers: Create complex cell content with React components
  • Event handlers: Respond to user interactions (sort, filter, paginate)
  • State management: Integrate with Redux, Context API, or local state

Here's an example with server-side data loading:

// src/components/ServerSideTable.jsx
import React, { useState, useCallback } from 'react';
import { GigaTables } from 'gigatables-react';

function ServerSideTable() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [pagination, setPagination] = useState({
    page: 1,
    pageSize: 10,
    total: 0
  });
  const [filters, setFilters] = useState({});
  const [sorting, setSorting] = useState({});

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams({
        page: pagination.page.toString(),
        pageSize: pagination.pageSize.toString(),
        ...filters,
        ...sorting
      });

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

      setData(result.data);
      setPagination(prev => ({
        ...prev,
        total: result.total
      }));
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  }, [pagination.page, pagination.pageSize, filters, sorting]);

  React.useEffect(() => {
    fetchData();
  }, [fetchData]);

  const handlePageChange = (page) => {
    setPagination(prev => ({ ...prev, page }));
  };

  const handleSort = (column, direction) => {
    setSorting({ [column]: direction });
  };

  const handleFilter = (column, value) => {
    setFilters(prev => ({
      ...prev,
      [column]: value
    }));
  };

  const columns = [
    { name: 'id', title: 'ID', sortable: true },
    { name: 'name', title: 'Name', sortable: true, filterable: true },
    { name: 'email', title: 'Email', sortable: true, filterable: true },
    { name: 'created', title: 'Created', sortable: true }
  ];

  return (
    <GigaTables
      data={data}
      columns={columns}
      loading={loading}
      pagination={{
        enabled: true,
        page: pagination.page,
        pageSize: pagination.pageSize,
        total: pagination.total,
        onPageChange: handlePageChange
      }}
      sorting={{
        enabled: true,
        onSort: handleSort
      }}
      filtering={{
        enabled: true,
        onFilter: handleFilter
      }}
    />
  );
}

export default ServerSideTable;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive admin dashboard table with advanced features:

// src/components/AdminDashboardTable.jsx
import React, { useState, useEffect, useCallback } from 'react';
import { GigaTables } from 'gigatables-react';

function AdminDashboardTable() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [selectedRows, setSelectedRows] = useState([]);
  const [pagination, setPagination] = useState({
    page: 1,
    pageSize: 20,
    total: 0
  });
  const [filters, setFilters] = useState({});
  const [sorting, setSorting] = useState({ column: 'id', direction: 'asc' });

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const queryParams = new URLSearchParams({
        page: pagination.page.toString(),
        limit: pagination.pageSize.toString(),
        sortBy: sorting.column,
        sortOrder: sorting.direction,
        ...Object.entries(filters).reduce((acc, [key, value]) => {
          if (value) acc[key] = value;
          return acc;
        }, {})
      });

      const response = await fetch(`/api/admin/users?${queryParams}`);
      const result = await response.json();

      setData(result.users);
      setPagination(prev => ({
        ...prev,
        total: result.total
      }));
    } catch (error) {
      console.error('Failed to fetch data:', error);
    } finally {
      setLoading(false);
    }
  }, [pagination.page, pagination.pageSize, filters, sorting]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const handleBulkAction = async (action) => {
    if (selectedRows.length === 0) return;

    try {
      const response = await fetch('/api/admin/users/bulk', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          action,
          ids: selectedRows
        })
      });

      if (response.ok) {
        setSelectedRows([]);
        fetchData();
      }
    } catch (error) {
      console.error('Bulk action failed:', error);
    }
  };

  const columns = [
    {
      name: 'id',
      title: 'ID',
      width: 80,
      sortable: true,
      render: (value, row) => (
        <input
          type="checkbox"
          checked={selectedRows.includes(row.id)}
          onChange={(e) => {
            if (e.target.checked) {
              setSelectedRows([...selectedRows, row.id]);
            } else {
              setSelectedRows(selectedRows.filter(id => id !== row.id));
            }
          }}
        />
      )
    },
    {
      name: 'avatar',
      title: 'Avatar',
      width: 80,
      render: (value) => (
        <img
          src={value || '/default-avatar.png'}
          alt="Avatar"
          style={{
            width: '40px',
            height: '40px',
            borderRadius: '50%',
            objectFit: 'cover'
          }}
        />
      )
    },
    {
      name: 'name',
      title: 'Full Name',
      sortable: true,
      filterable: true,
      render: (value, row) => (
        <div>
          <strong>{value}</strong>
          <div style={{ fontSize: '12px', color: '#666' }}>
            {row.email}
          </div>
        </div>
      )
    },
    {
      name: 'role',
      title: 'Role',
      sortable: true,
      filterable: true,
      render: (value) => {
        const colors = {
          admin: '#dc3545',
          manager: '#ffc107',
          user: '#28a745'
        };
        return (
          <span
            style={{
              padding: '4px 8px',
              borderRadius: '4px',
              backgroundColor: colors[value] || '#6c757d',
              color: 'white',
              fontSize: '12px',
              fontWeight: 'bold'
            }}
          >
            {value.toUpperCase()}
          </span>
        );
      }
    },
    {
      name: 'status',
      title: 'Status',
      sortable: true,
      filterable: true,
      render: (value) => (
        <span
          style={{
            display: 'inline-block',
            width: '10px',
            height: '10px',
            borderRadius: '50%',
            backgroundColor: value === 'active' ? '#28a745' : '#dc3545',
            marginRight: '8px'
          }}
        />
      )
    },
    {
      name: 'lastLogin',
      title: 'Last Login',
      sortable: true,
      render: (value) => {
        if (!value) return 'Never';
        const date = new Date(value);
        return date.toLocaleDateString('en-US', {
          year: 'numeric',
          month: 'short',
          day: 'numeric',
          hour: '2-digit',
          minute: '2-digit'
        });
      }
    },
    {
      name: 'actions',
      title: 'Actions',
      width: 150,
      render: (value, row) => (
        <div>
          <button
            onClick={() => handleEdit(row.id)}
            style={{
              marginRight: '8px',
              padding: '4px 8px',
              border: '1px solid #007bff',
              backgroundColor: 'white',
              color: '#007bff',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            Edit
          </button>
          <button
            onClick={() => handleDelete(row.id)}
            style={{
              padding: '4px 8px',
              border: '1px solid #dc3545',
              backgroundColor: 'white',
              color: '#dc3545',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            Delete
          </button>
        </div>
      )
    }
  ];

  const handleEdit = (id) => {
    console.log('Edit user:', id);
    // Implement edit logic
  };

  const handleDelete = async (id) => {
    if (window.confirm('Are you sure you want to delete this user?')) {
      try {
        await fetch(`/api/admin/users/${id}`, { method: 'DELETE' });
        fetchData();
      } catch (error) {
        console.error('Delete failed:', error);
      }
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <div style={{ marginBottom: '20px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <h2>Admin Dashboard</h2>
        <div>
          {selectedRows.length > 0 && (
            <>
              <button
                onClick={() => handleBulkAction('activate')}
                style={{ marginRight: '8px', padding: '8px 16px' }}
              >
                Activate Selected ({selectedRows.length})
              </button>
              <button
                onClick={() => handleBulkAction('deactivate')}
                style={{ marginRight: '8px', padding: '8px 16px' }}
              >
                Deactivate Selected
              </button>
              <button
                onClick={() => handleBulkAction('delete')}
                style={{ padding: '8px 16px', backgroundColor: '#dc3545', color: 'white', border: 'none' }}
              >
                Delete Selected
              </button>
            </>
          )}
        </div>
      </div>

      <GigaTables
        data={data}
        columns={columns}
        loading={loading}
        pagination={{
          enabled: true,
          page: pagination.page,
          pageSize: pagination.pageSize,
          total: pagination.total,
          onPageChange: (page) => setPagination(prev => ({ ...prev, page }))
        }}
        sorting={{
          enabled: true,
          column: sorting.column,
          direction: sorting.direction,
          onSort: (column, direction) => setSorting({ column, direction })
        }}
        filtering={{
          enabled: true,
          filters: filters,
          onFilter: (column, value) => {
            setFilters(prev => ({
              ...prev,
              [column]: value
            }));
            setPagination(prev => ({ ...prev, page: 1 }));
          }}
        }}
      />
    </div>
  );
}

export default AdminDashboardTable;
Enter fullscreen mode Exit fullscreen mode

This advanced example demonstrates:

  • Server-side data loading with pagination, sorting, and filtering
  • Custom cell renderers with complex components
  • Row selection and bulk actions
  • Real-time data updates
  • Custom action buttons per row
  • Loading states and error handling
  • Responsive design considerations

Common Issues / Troubleshooting

  1. Data not loading: Ensure your API endpoints return data in the expected format. Check network requests in browser DevTools and verify CORS settings if calling external APIs.

  2. Sorting/filtering not working: Verify that your column definitions have sortable: true or filterable: true set, and that your data handler functions are properly connected to the table events.

  3. Performance issues with large datasets: Implement server-side processing instead of loading all data at once. Use pagination and lazy loading for better performance.

  4. Custom renderers not updating: Make sure your render functions are pure and don't depend on external state that might not trigger re-renders. Use React.memo for expensive render functions.

  5. TypeScript errors: Install proper type definitions and ensure your column definitions match the expected interface structure.

Next Steps

Now that you've mastered advanced GigaTables React features:

  • Explore custom plugins and extensions
  • Implement real-time data synchronization with WebSockets
  • Add advanced filtering with multiple conditions
  • Create custom export functionality (CSV, Excel, PDF)
  • Integrate with state management libraries (Redux, Zustand)
  • Build reusable table components and hooks
  • Check the official repository: https://github.com/GigaTables/reactables
  • Look for part 4 of this series for more advanced topics

Summary

You've learned how to implement advanced data management features with GigaTables React, including server-side processing, custom rendering, bulk operations, and complex interactions. The library provides a robust foundation for building enterprise-grade data tables with sophisticated functionality and excellent performance.

Top comments (0)