recoil-table
TypeScript icon, indicating that this package has built-in type declarations

0.1.3 • Public • Published

Recoil Table

A lightweight and flexible table state manager built using Recoil.

Purpose

Recoil Table is an experimental package that is intended to make managing the state of a table or grid simple.

By leveraging Recoil your components can access the table state from anywhere in your application under the RecoilRoot and listen only to the parts of the state that are necessary for them to render.

It is headless and does not provide any UI components, just the tools to manage the underlying state of the table.

Getting Started

Installation

npm i recoil-table

yarn add recoil-table

Coming soon

RecoilRoot

Because Recoil Table is built using Recoil, the RecoilRoot must appear somewhere in the parent tree. If you are unfamiliar with Recoil, you may find it useful to explore their docs and go through the basic tutorial

import React from 'react';
import { RecoilRoot } from 'recoil';

function App() {
  return (
    <RecoilRoot>
      <MyApp />
    </RecoilRoot>
  );
}

Atoms and Selectors

At it's core, Recoil Table is simply a collection of Recoil Atom and Selector Families. Use them in combination with any of the hooks provided by Recoil (useRecoilValue, useRecoilState, etc...) and pass them a key that is unique to the table state you wish to access.

import { useRecoilValue } from 'recoil';
import { columnsAtom } from 'recoil-table';

function TableColumns() {
  // access columns for table1
  const columns = useRecoilValue(columnsAtom('table1'));

  return (
    <TableRow>
      {columns.map((column) => (
        <TableCell>{column.Header}</TableCell>
      ))}
    </TableRow>
  );
}

useTable

Recoil Table provides a useTable hook, which will forward the unique table key to all the Atom and Selector Families for you.

import { useRecoilValue } from 'recoil';
import { useTable } from 'recoil-table';

function TableColumns() {
  const { columnsAtom } = useTable('table1');
  const columns = useRecoilValue(columnsAtom);

  return (
    <TableRow>
      {columns.map((column) => (
        <TableCell>{column.Header}</TableCell>
      ))}
    </TableRow>
  );
}

Complex Example

This is a rough look at what a more complete Table may look like and can be found here

const COLUMNS = [
  {
    Header: 'Age',
    accessor: 'age',
  },
  {
    Header: 'Visits',
    accessor: 'visits',
  },
  {
    Header: 'Status',
    accessor: 'status',
  },
];

function RecoilTable() {
  const tableInstance = useTable<Data>('table1');
  const { dataAtom, columnTemplatesAtom } = tableInstance;
  const setData = useSetRecoilState(dataAtom);
  const setColumns = useSetRecoilState(columnTemplatesAtom);

  React.useEffect(() => {
    setColumns(COLUMNS);
  }, [setColumns, tableInstance]);

  React.useEffect(() => {
    async function fetchData() {
      const response = await asyncDataFetch();
      setData(response.data);
    }
    fetchData();
  }, [setData]);

  return (
    <>
      <RecoilTable>
        <RecoilTableHeader tableInstance={tableInstance} />
        <RecoilTableBody tableInstance={tableInstance} rowSelection />
      </RecoilTable>
      <RecoilTablePagination tableInstance={tableInstance} />
    </>
  );
}
//RecoilTableHeader.tsx
function RecoilTableHeader({ tableInstance }) {
  const columns = useRecoilValue(tableInstance.columnsAtom);
  return (
    <TableHead>
      <TableRow>
        {columns.map((column) => (
          <TableHeaderCell column={column} tableInstance={tableInstance} />
        ))}
      </TableRow>
    </TableHead>
  );
}
// RecoilTableBody.tsx
function RecoilTableBody({ tableInstance, rowSelection }) {
  const { rows } = useRecoilValue(tableInstance.rowsAtom);
  return (
    <TableBody>
      {rows.map((row) => (
        <TableRow
          row={row}
          tableInstance={tableInstance}
          rowSelection={rowSelection}
        />
      ))}
    </TableBody>
  );
}

API

The following is a list of all exported Atoms. Atoms can either be imported directly, or accessed via the tableInstance returned from the useTable hook.

Atoms can be used with the hooks provided from Recoil like so:

import {useRecoilValue, useSetRecoilState. useRecoilState} from 'recoil';
import { columnTemplatesAtom, useTable } from 'recoil-table';

...

// access from direct import
const columns = useRecoilValue(columnTemplatesAtom('table1'));

// or from useTable hook

const tableInstance = useTable('table1');
const columns = useRecoilValue(tableInstance.columnTemplates);
const setColumns = useSetRecoilState(tableInstance.columnTemplates);
const [columns, setColumns] = useRecoilState(tableInstance.columnTemplates);

Some Atoms may be marked as ReadOnly and should only be used with useRecoilValue. Trying to setState on those atoms will result in undefined behaviors.

Columns

  • columnTemplatesAtom: RecoilState<Column[]>
    
    • Set or get list of original column definitions

 

  • columnsAtom
    
    • Gets the list of columns that should be visible on the table
    • ReadOnly

 

  • columnHideAtom: (columnId: string) => RecoilState<boolean>
    • True if the column with the given ID is visible

 

  • columnSortAtom: (columnId: string) => {
        isSorted: boolean,
        isDesc: boolean,
      }
    
    • Get the sort state of a specific column
    • Should NOT be used to set the column state. Use selectSort to set instead.
    • ReadOnly

 

  • sortAtom: RecoilState<{ columnId: string, isDesc: boolean }>,
    
    • Get or Set which column is actively being sorted
    • RecoilTable currently only supports single column sort

 

Data and Rows

  • dataAtom: Object[]
    
    • Get or Set the original data for the table

     

  • rowsAtom: Row[]
    
    • Get the list of rows that should be displayed on the table
    • This is a subset of the original Data that has been Sorted and Paginated
    • ReadOnly

 

  • selectedRowsAtom: Record<RowId, boolean>
    
    • Get or Set the list of currently selected Rows

 

  • rowSelectionAtom:  (rowId: string) => RecoilState<boolean>
    • Get the current selection state for a given row
    • ReadOnly

 

Pagination

  • pageAtom: RecoilState<{
      page: 0,
      rowsPerPage: 10,
    }>
    • Get or Set the pagination state
    • page - current page

 

TableConfig

  • configAtom: config
    
    • Get or Set the options for the table
    • manualControl: boolean
      
      • default false
      • if True, rows will skip Pagination and Sorting and return the Data
      • Why not just use dataAtom? Because rows also assigns each row a unique ID needed for selection.

Package Sidebar

Install

npm i recoil-table

Weekly Downloads

1

Version

0.1.3

License

MIT

Unpacked Size

39.4 kB

Total Files

22

Last publish

Collaborators

  • rbaxter