SmartGrid: Light, customisable & multi grid with minimal config. 
Tags: react, showdev, javascript, weeklyui
Published: 2021-07-31 11:36:12

Introducing smart grid, a lightweight [116 B](https://bundlephobia.com/package/@crafts/smart-grid@latest), customisable (UI is up to you), multigrid (multiple pinned columns/grids) all with minimal config.

Smart Grid is not a component anymore as it was in v1 but a React hook, making UI customisable as much as a developer wants, instead of depending upon the library to create features or provide support, make your own.

Smart Grid provides required methods enabling core table features without hassle so you can focus more on UI and other important features.


## Smart Grid API

```jsx
const { onScroll, rowRenderer } = useGrid({
    data: state.data,
    rowHeight: 40,
    buffer: 10,
    limit: 20,
    loadMore: getData,
    // true by default
    virtualized: true
  });
```

```jsx
      <table role="table">
        <thead>
          <tr role="row">
            <th role="cell" colSpan={4}></th>
            <th role="cell" colSpan={3}>
              Car
            </th>
          </tr>
          <tr role="row">
            <th colSpan={1} role="cell">
              First Name
            </th>
            <th colSpan={1} role="cell">
              Last Name
            </th>
            <th colSpan={1} role="cell">
              Age
            </th>
            <th colSpan={1} role="cell">
              Email
            </th>
            <th colSpan={1} role="cell">
              Make
            </th>
            <th colSpan={1} role="cell">
              Model
            </th>
            <th colSpan={1} role="cell">
              Year
            </th>
          </tr>
        </thead>
        <tbody
          role="rowgroup"
          onScroll={onScroll}
        >
          {rowRenderer((row, style, index, ref) =>
              <tr
                role="row"
                ref={ref}
                className="table-row"
                data-testid={`table-row-${index}`}
                style={style}
                key={index}
              >
                <td role="cell">{row.firstName}</td>
                <td role="cell">{row.lastName}</td>
                <td role="cell">{row.age}</td>
                <td role="cell">{row.email}</td>
                <td role="cell">{row.carMake}</td>
                <td role="cell">{row.carModel}</td>
                <td role="cell">{row.carYear}</td>
              </tr>
          )}
        </tbody>
      </table>
```

That's it, you can pass `virtualized` as `false` in the case of small tables to increase the performance. If you need to apply any filter on like sorting or filtering, you can do that to it.

```jsx
const filteredData = React.useMemo(() => filter(state.data), [...])
const { onScroll, rowRenderer } = useGrid({
    data: filter(state.data),
    rowHeight: 40,
    buffer: 10,
    limit: 20,
    loadMore: getData,
    // true by default
    virtualized: true
  });
```

If you are table supports column setting, I would advice you to maintain a schema for columns and using that schema to show/hide columns. 

Benefit of keeping these things out `useGrid` is, first the UI: it's totally upto your logic which remains outside, you don't have to use any hacks and smart grid is focused on what it should do.

---

### Pinned Columns | MultiGrid

Pinned columns are possible through multiple grids using `useGrids` and are little complicated than `useGrid` where only 2 properties were sufficient to create a grid here the case is different

```jsx
const {
    onScroll,
    rowRenderers,
    tableHeight,
    tableRef,
    GridHeaders,
    GridBodies,
    ScrollBars,
  } = useGrids(3, {
    data: loading.current ? data.concat([null, null]) : data,
    rowHeight: 40,
    buffer: 10,
    limit:20,
    dynamicHeight: true,
    loadMore: getData,
  });
```
`GridHeaders`, `GridBodies`, `ScrollBars` are just div with internal `refs`. In multi grid a lot happens which is not in scope for this introductory blog, you can visit the [doc](https://smartgrid.mukulja.in/api/useGrids) for more.

---

## Why Smart Grid

There are tones of table/grid libraries out there, do we need one more? How does it stand out?

I will compare it with 3 awesome tables out there

1. [React Virtualized](https://github.com/bvaughn/react-virtualized)
2. [AG Grid](https://www.ag-grid.com/)
3. [React Table](https://react-table.tanstack.com/)

|                    | Smart Grid | Ag Grid | React Virtualized | React Table |
|--------------------|------------|---------|-------------------|-------------|
| Size               | 116 Bytes  | 200 kb+ | 27.4 kb           | 8 - 15+ kb  |
| MultiGrid          | Yes        | Yes     | Yes               | No          |
| Scroll Sync        | Yes        | Yes     | No                | NA          |
| Hooks              | Yes        | No      | No                | Yes         |
| Write your table UI | Yes        | No      | No                | Yes         |

**Scroll Sync:** It's an issue where the scroll bar for 2 tables goes out of sync. It's not a bug in the table but that's how the browser handles scrolling 

### AG Grid

Ag Grid is one the best and most feature-loaded grid out there only bad thing is its size so for smaller projects it's not the best choice to go ahead with it. You can customize the UI but there always will be limitations as things are abstracted from you. This was the original inspiration that led to the development of Smart Grid.

### React Virtualized 

Another awesome component, the only problem with it is the scroll sync issue, the size and customization.

### React Table

React table is in active support and hook based library. It got a lot of features and plugins at your fingertips where it lacks is multi grids and a little learning curve, as it got a lot of pre-defined API/plugins, they also contribute to size. 

Each library has its pros & cons at the end it's about the requirements.

Repo: https://github.com/mukuljainx/smart-grid
Doc: https://smartgrid.mukulja.in/

Thank you, Reader. I would be very happy to hear out your feedback & views in the comment. 

--EOF--