react-smart-table-component
TypeScript icon, indicating that this package has built-in type declarations

1.2.1 • Public • Published

react-smart-table-component

npm version npm npm

An intelligent, dynamic React component, built entirely with TypeScript. This component is equipped with built-in features such as infinite scrolling, pagination, search and now includes the newly added sorting functionality. It provides a seamless user experience for data-intensive applications, allowing for efficient navigation and organization of data.

CodeSandbox

Live Demo

Features

  • Support of React 18, NextJS and Typescript
  • Use custom types for headings and body
  • Can use default CSS or add your customized styles
  • Option for both Pagination and Infinite scroll feature (Default scroll and Upside down scroll)
  • Scoped fields option to use custom JSX in any cell of the table

Installation

NPM

To install the latest stable version:

npm install --save react-smart-table-component

Basic usage:

import React from "react";
import SmartTable from "react-smart-table-component";

export default function Users({ loading, data }) {
  return (
    <SmartTable
      items={data}
      headings={[
        { fieldName: "name", title: "Name" },
        { fieldName: "email", title: "Email" },
        { fieldName: "phone", title: "Phone" },
        { fieldName: "address", title: "Address" },
        { fieldName: "company", title: "Company" },
      ]}
      loading={loading}
      scopedFields={{
        address: (item) => (
          <td>{`${item.address.street}, ${item.address.city}, ${item.address.state}, ${item.address.zipcode}`}</td>
        ),
        company: (item) => (
          <td>{`${item.company.name}, ${item.company.branch}`}</td>
        ),
      }}
    />
  );
}
Sample code for Next.JS (TypeScript)
import Head from "next/head";
import Link from "next/link";
import dynamic from "next/dynamic";

import { UserInfo } from "@/typings";

const ReactSmartTableComponent = dynamic(
  () => import("react-smart-table-component"),
  {
    ssr: false,
    loading: () => <p>Loading...</p>,
  }
);

export default function Users({ users }: { users: UserInfo[] }) {
  return (
    <>
      <Head>
        <title>Users List</title>
        <meta name="description" content="Users Page" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <ReactSmartTableComponent
        search
        parentClass="container mt-5"
        className="table table-responsive table-light table-striped"
        items={users as UserInfo[]}
        headings={[
          { fieldName: "id", title: "#" },
          { fieldName: "username", title: "Username", sortable: true },
          { fieldName: "name", title: "Name", sortable: true },
          { fieldName: "email", title: "Email", sortable: true },
          { fieldName: "phone", title: "Phone", sortable: true },
          { fieldName: "website", title: "Website", sortable: true },
          {
            fieldName: "address",
            title: "Address",
            colSpan: 3,
          },
        ]}
        scopedFields={{
          id: (item) => <td>{item.id}.</td>,
          username: (item) => (
            <td style={{ color: "#00aaff" }}>
              <Link href={`/users/${item.id}`}>{item.username}</Link>
            </td>
          ),
          address: (item) => (
            <>
              <td>{item.address.suite}</td>
              <td>{item.address.street}</td>
              <td>{`${item.address.city} ${item.address.zipcode}`}</td>
            </>
          ),
        }}
      />
    </>
  );
}

export async function getStaticProps() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users");
  const data = await response.json();
  return {
    props: {
      users: data,
    },
  };
}
Sample code for React.JS (Infinite Scroll)
import { useState, useEffect, useRef, useCallback } from "react";

import ReactSmartTableComponent from "react-smart-table-component";

import "react-smart-table-component/dist/styles.css";

export default function App() {
  const [products, setProducts] = useState([]);
  const [offset, setOffset] = useState(0);
  const [hasMore, setHasMore] = useState(false);
  const [loading, setLoading] = useState(false);

  const offsetRef = useRef(offset);
  const hasMoreRef = useRef(hasMore);
  const productsRef = useRef(products);

  useEffect(() => {
    hasMoreRef.current = hasMore;
    offsetRef.current = offset;
    productsRef.current = products;
  }, [offset, hasMore, products]);

  const fetchProducts = useCallback(
    async (firstLoad) => {
      setLoading(true);
      const data = await fetch(
        `https://dummyjson.com/products?limit=10&skip=${offsetRef.current}&select=title,price,brand,category,thumbnail,rating,description`,
        { headers: { "Accept-Encoding": "gzip,deflate,compress" } }
      ).then((data) => data.json());
      if (data && data.products) {
        if (data.products.length < 10) setHasMore(false);
        else setHasMore(true);

        setOffset(firstLoad ? 10 : offsetRef.current + 10);
        const records = firstLoad
          ? data.products
          : [...productsRef.current, ...data.products];
        setProducts(records);
      }
      setLoading(false);
    },
    [products, offsetRef, productsRef]
  );

  useEffect(() => {
    fetchProducts(true);
  }, []);

  /**
   * Load more records
   */
  const loadMore = () => {
    setTimeout(() => {
      if (hasMoreRef.current) {
        fetchProducts(false);
      }
    }, 500);
  };

  return (
    <ReactSmartTableComponent
      headings={[
        { fieldName: "thumbnail", title: "Thumbnail" },
        { fieldName: "title", title: "Title" },
        { fieldName: "price", title: "Price", sortable: true },
        { fieldName: "brand", title: "Brand" },
        { fieldName: "category", title: "Category" },
        { fieldName: "rating", title: "Rating", sortable: true },
        { fieldName: "description", title: "Description" },
        { fieldName: "action_1", title: "Action" },
      ]}
      search
      recordsView="infinite-Scroll"
      className="theme-table"
      items={products}
      loading={loading}
      loadMore={loadMore}
      hasMoreRecords={hasMore}
      scopedFields={{
        thumbnail: (item) => (
          <td>
            <img
              src={item.thumbnail}
              alt="thumbnail"
              height={100}
              width={100}
            />{" "}
          </td>
        ),
        action_1: (item) => (
          <td>
            <button
              onClick={() =>
                alert(
                  `Item Name: ${item.title}\nItem Price: ${item.price}\nItem Brand: ${item.brand}\nItem Description: ${item.description}`
                )
              }
            >
              View More
            </button>
          </td>
        ),
      }}
    />
  );
}

API

Name Type Required Default Description
items array true Array Provide the data list which you wanna iterate through
headings object true Array The headings of the table
scopedFields object false undefined You can customize the layout of a particular cell via using this prop. Pass your custom cell body
loading boolean false undefined This provides a loading text
onRowClick function false undefined It provides the row info on which the user clicks
customLoader React Node false undefined You can provide a custom loader of the table
recordsView string false undefined You can provide the data view pattern as either 'infinite-Scroll' or 'pagination'
inverseScroll boolean false undefined The default behaviour of infinite scroll is scroll to down but if you pass this prop, inverse scroll will work upside down
hasMoreRecords boolean false undefined It is a flag to indicate the component that there are more records to display so that it can trigger loadMore function
loadMore function false undefined This method is called when the table scroll cross the threshold
totalPages number false undefined Total number of pages
currentPage number false undefined Current page value
onPageChange function false undefined It returns the clicked page number
parentClass string false scrollable-area You can pass a parent wrapper class for the table to customize the styles. scrollable-area is a default class with some basic styles required for infinite scroll feature such as height, overflow etc.
search boolean works conditionally undefined To get a search box for searching functionality, (search and searchableFields both props are co-related to each other, if you pass one of these prop, you also need to pass the other)
searchableFields Array works conditionally undefined Pass the array of fields on which you want to perform the search (search and searchableFields both props are co-related to each other, if you pass one of these prop, you also need to pass the other)
searchBoxPlaceholder string false undefined Placeholder text for search box
stopDefaultSearch boolean false undefined Use this prop if you don't want to use the default search logic and want to implement your own search logic
searchType default | fuzzy false undefined Search type
onSearch (searchTerm: string) => void works conditionally undefined Event handler for the change event of search box
searchBehavior debounce | throttle works conditionally undefined Search behavior: How onSearch will receive the input value
noRecordsFound React.ReactNode | string false No record found Default text for empty data set is passed table items

Dependencies (0)

    Dev Dependencies (19)

    Package Sidebar

    Install

    npm i react-smart-table-component

    Weekly Downloads

    131

    Version

    1.2.1

    License

    MIT

    Unpacked Size

    34.6 kB

    Total Files

    6

    Last publish

    Collaborators

    • rawasthi231