DEV Community

Abdul Rehman
Abdul Rehman

Posted on

How to create Dynamic Tables in React js

Let's talk about Dynamic Tables which is a very common problem. We will do this without using any third party library. Let's see the problem we are dealing with. The issue is, we normally have many kind of data available in our application and we need to render that into the table. So instead of writing all kind of CSS and HTML over and over again, why not create a generic Table component and pass a JavaScript Object array to it. The Table Component will automatically render the Object Array.

Basic DynamicTable Component

So let's create a basic dynamic table component which accept two core props, one is the actual data to display in the table, second is the schema which tells have two basic information, one is label second is key, we can optionally pass classes or width kind of data. So our DynamicTable component props interface would look something like following

interface TableProps {
  data: { [key: string]: any }[];
  schema: { label: string; key: string;width:string}[];
  onUpdate?: (id: string | number) => void;
  onDelete?: (id: string | number) => void;
}
Enter fullscreen mode Exit fullscreen mode

Here you may notice we additionally passed two more functions into the props interface, one is onUpdate which is optional, second is onDelete which is also optional.
The main reason for using these props is to tell the parent component is that specific row is requested to be updated or delete. These two functions are also a basic need when we have to update or delete a specific row level data.

Rendering the Table

Now let's focus on the actual rendering process. As you may already guessed that we have to look into the schema table and render the data object. That will look basically something like following,

  <div>

      <table className="table-auto w-full text-left overflow-x-auto">
        <thead
          className="bg-gray-800 text-white"
          onClick={() => setSelectedIndex(-1)}
        >
          <tr>
            {schema.map((col, index) => (

              <th key={index} className= {`px-4 py-2 `}>
                {col.label}
              </th>

            ))}
            {(onUpdate || onDelete) && <th className="px-4 py-2 w-52">Actions</th>}
          </tr>
        </thead>
        <tbody>
          {data.map((row, index) => (
            <tr
              key={index}
              className={`${
                index === selectedIndex ? "bg-gray-500" : ""
              } hover:bg-gray-500/75`}
              onClick={() => setSelectedIndex(index)}
            >
              {schema.map((col, colIndex) => (
                <td key={colIndex} className={`border px-4 py-2 `}>
                  {row[col.key]}
                </td>
              ))}
              {(onUpdate || onDelete) && (
                <td className="border px-4 py-2">
                  {onUpdate && (
                    <button
                      className="bg-blue-500 hover:bg-blue-400 text-white font-medium py-2 px-4 rounded-lg mr-2"
                      onClick={() => {
                        onUpdate(row.id);

                      }}
                    >
                     <FaEdit/>
                    </button>
                  )}
                  {onDelete && (
                    <button
                      className="bg-red-500 hover:bg-red-400 text-white font-medium py-2 px-4 rounded-lg"
                      onClick={() => {
                        onDelete(row.id);

                      }}
                    >
                      <FaTrash/>
                    </button>
                  )}
                </td>
              )}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
Enter fullscreen mode Exit fullscreen mode

We had used the React Icons library and used the Fa icons for rendering the action buttons for update or delete actions.

Compete DynamicTable Component Code

Here is the complete component code for rendering the dynamic table according to above mentioned procedure.

import React, { useState } from "react";
import { FaEdit, FaTrash } from "react-icons/fa";


interface TableProps {
  data: { [key: string]: any }[];
  schema: { label: string; key: string;width:string}[];
  onUpdate?: (id: string | number) => void;
  onDelete?: (id: string | number) => void;
}

const DynamicTable: React.FC<TableProps> = ({
  data,
  schema,
  onUpdate,
  onDelete,
}) => {
  const [selectedIndex, setSelectedIndex] = useState(-1);

  return (
    <div>

      <table className="table-auto w-full text-left overflow-x-auto">
        <thead
          className="bg-gray-800 text-white"
          onClick={() => setSelectedIndex(-1)}
        >
          <tr>
            {schema.map((col, index) => (

              <th key={index} className= {`px-4 py-2 `}>
                {col.label}
              </th>

            ))}
            {(onUpdate || onDelete) && <th className="px-4 py-2 w-52">Actions</th>}
          </tr>
        </thead>
        <tbody>
          {data.map((row, index) => (
            <tr
              key={index}
              className={`${
                index === selectedIndex ? "bg-gray-500" : ""
              } hover:bg-gray-500/75`}
              onClick={() => setSelectedIndex(index)}
            >
              {schema.map((col, colIndex) => (
                <td key={colIndex} className={`border px-4 py-2 `}>
                  {row[col.key]}
                </td>
              ))}
              {(onUpdate || onDelete) && (
                <td className="border px-4 py-2">
                  {onUpdate && (
                    <button
                      className="bg-blue-500 hover:bg-blue-400 text-white font-medium py-2 px-4 rounded-lg mr-2"
                      onClick={() => {
                        onUpdate(row.id);

                      }}
                    >
                     <FaEdit/>
                    </button>
                  )}
                  {onDelete && (
                    <button
                      className="bg-red-500 hover:bg-red-400 text-white font-medium py-2 px-4 rounded-lg"
                      onClick={() => {
                        onDelete(row.id);

                      }}
                    >
                      <FaTrash/>
                    </button>
                  )}
                </td>
              )}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default DynamicTable;
Enter fullscreen mode Exit fullscreen mode

Using this Component

Now that we have our DynamicTable Component ready, you may want to know the basic example to use that component. Here we have basic usage example for this DynamicTable component.

import React from "react";
import DynamicTable from "../Dynamic/DynamicTable";


const schema = [
  { key: "id", label: "ID",width:'32'},
  { key: "name", label: "Name",width:'32' },
  { key: "email", label: "Email",width:'64' },
  { key: "age", label: "Age" ,width: '32'},
];

const data = [
  { id: 1, name: "John Doe", email: "johndoe@example.com", age: 32 },
  { id: 2, name: "Jane Doe", email: "janedoe@example.com", age: 28 },
  { id: 3, name: "Bob Smith", email: "bobsmith@example.com", age: 35 },
];

function StoreOwnerTable() {

  const handleUpdate = (id: string | number) => {
    console.log(`Update row: ${id}`);
  };

  const handleDelete = (id: string | number) => {
    console.log(`Delete row: ${id}`);
  };





  return (
    <div className="container mx-auto ">

      {simpleUsers ? (
        <DynamicTable
          schema={schema}
          data={data}
          onUpdate={handleUpdate}
          onDelete={handleDelete}
        />
      ) : null}

    </div>
  );
}

export default StoreOwnerTable;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)