Building Dynamic and Responsive Tables in React

Last updated 2 months, 2 weeks ago | 113 views 75     5

Tags:- React

Introduction: Why React Tables Matter

In almost every data-driven application—be it a dashboard, CRM, or admin panel—tables are critical for displaying structured information. But building efficient, responsive, and feature-rich tables from scratch can be time-consuming.

React offers multiple ways to build tables:

  • Plain JSX tables (good for simple use-cases)

  • React Table library (perfect for complex features like sorting, filtering, and pagination)

Problem Solved: Tables built with React enable dynamic rendering, improve maintainability, and scale easily with large data sets.


Rendering a Basic Table Using JSX

Let’s begin by building a simple static table using plain JSX.

✅ Step 1: Sample Data

const users = [
  { id: 1, name: 'Alice', email: '[email protected]' },
  { id: 2, name: 'Bob', email: '[email protected]' },
  { id: 3, name: 'Charlie', email: '[email protected]' }
];

✅ Step 2: JSX Table Component

function BasicTable() {
  return (
    <table border="1" cellPadding="10">
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
        </tr>
      </thead>
      <tbody>
        {users.map(user => (
          <tr key={user.id}>
            <td>{user.id}</td>
            <td>{user.name}</td>
            <td>{user.email}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

⚙️ Building Advanced Tables Using react-table

For advanced use-cases like sorting, filtering, pagination, and custom cell rendering, the react-table library is highly recommended.

✅ Step 1: Install react-table

npm install react-table

✅ Step 2: Define Columns and Data

import { useTable } from 'react-table';

const data = [
  { id: 1, name: 'Alice', role: 'Admin' },
  { id: 2, name: 'Bob', role: 'Editor' },
  { id: 3, name: 'Charlie', role: 'Viewer' }
];

const columns = [
  {
    Header: 'ID',
    accessor: 'id' // accessor is the "key" in the data
  },
  {
    Header: 'Name',
    accessor: 'name'
  },
  {
    Header: 'Role',
    accessor: 'role'
  }
];

✅ Step 3: Create a Table Using useTable

function ReactTableComponent() {
  const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
    useTable({ columns, data });

  return (
    <table {...getTableProps()} border="1" cellPadding="10">
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            {headerGroup.headers.map(col => (
              <th {...col.getHeaderProps()}>{col.render('Header')}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map(row => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              {row.cells.map(cell => (
                <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
              ))}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

✅ Full Working Example with react-table

import React from 'react';
import { useTable } from 'react-table';

const TableComponent = () => {
  const data = React.useMemo(
    () => [
      { id: 1, name: 'Alice', role: 'Admin' },
      { id: 2, name: 'Bob', role: 'Editor' },
      { id: 3, name: 'Charlie', role: 'Viewer' }
    ],
    []
  );

  const columns = React.useMemo(
    () => [
      { Header: 'ID', accessor: 'id' },
      { Header: 'Name', accessor: 'name' },
      { Header: 'Role', accessor: 'role' }
    ],
    []
  );

  const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
    useTable({ columns, data });

  return (
    <table {...getTableProps()} style={{ border: '1px solid #ccc', width: '100%' }}>
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()} style={{ backgroundColor: '#f5f5f5' }}>
            {headerGroup.headers.map(col => (
              <th {...col.getHeaderProps()} style={{ padding: 10 }}>{col.render('Header')}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map(row => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              {row.cells.map(cell => (
                <td {...cell.getCellProps()} style={{ padding: 10 }}>{cell.render('Cell')}</td>
              ))}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
};

export default TableComponent;

Feature Comparison: JSX vs React Table

Feature JSX Table react-table
Dynamic rendering ✅ Yes ✅ Yes
Sorting ❌ Manual ✅ Built-in
Filtering ❌ Manual ✅ Built-in
Pagination ❌ Manual ✅ Add-on support
Custom cell rendering ✅ With effort ✅ Easier & flexible
Lightweight ✅ Yes ⚠️ Medium-sized bundle

⚠️ Tips & Common Pitfalls

✅ Tips

  • Use React.memo for rows in large tables.

  • For API data, fetch and set it with useEffect() + useState().

  • Use react-table plugins for additional features (e.g., pagination, global filter).

❌ Common Pitfalls

Mistake Problem Solution
Missing key in list elements React warning, re-render issues Always use a unique identifier
Large data tables in JSX Performance degradation Use virtualization (e.g., react-virtual)
Forgetting to memoize data/columns Unnecessary re-renders Use React.useMemo()
Copy/paste Bootstrap classes May conflict with table layout Use inline styles or utility classes

Conclusion: Choose the Right Table Strategy in React

React gives you flexibility—use simple JSX for basic tables, and react-table for robust, scalable features.

Best Practices:

  • Keep data and columns separate and reusable.

  • Use memoization for performance.

  • Avoid manually building sort/filter logic—use libraries when complexity grows.