reCAPTCHA WAF Session Token
Programming Languages

How to Create a Sortable and Filterable Table in React — SitePoint

Dynamic tables are often used in web applications to represent data in a structured format. Sorting and filtering the dataset can speed up processes when working with large sets of data. In this tutorial, we’ll take a look at how to create a sortable and filterable table component in React.

You can find the full source code in one piece hosted on GitHub. The end result is pictured below.

Table of Contents

Prerequisites

Before we begin, this tutorial assumes you have a basic knowledge of HTML, CSS, JavaScript, and React. While we go over the project step by step, we won’t explain core concepts in React or JavaScript array methods in detail. We’ll also use TypeScript, but the same can be achieved without it. With that being said, let’s jump into coding.

Setting Up The Project

For this project, we’ll use Vite, a robust and popular frontend tool. If you don’t already have an existing React application, you can bootstrap a new project in Vite using one of the following commands inside your terminal:

<code class="yaml language-yaml">
npm create vite@latest folder<span class="token punctuation">-</span>name <span class="token punctuation">-</span><span class="token punctuation">-</span> <span class="token punctuation">-</span><span class="token punctuation">-</span>template react<span class="token punctuation">-</span>ts


yarn create vite folder<span class="token punctuation">-</span>name <span class="token punctuation">-</span><span class="token punctuation">-</span>template react<span class="token punctuation">-</span>ts


pnpm create vite folder<span class="token punctuation">-</span>name <span class="token punctuation">-</span><span class="token punctuation">-</span>template react<span class="token punctuation">-</span>ts


bunx create<span class="token punctuation">-</span>vite folder<span class="token punctuation">-</span>name <span class="token punctuation">-</span><span class="token punctuation">-</span>template react<span class="token punctuation">-</span>ts
</code>

Once you’re ready, set up a new folder for the Table component within the React project with the following structure:

<code class="yaml language-yaml">src
├─ components
│  ├─ Table
│  │  ├─ index.ts 
│  │  ├─ table.css
│  │  ├─ Table.tsx
├─ App.tsx
</code>
  • index.ts. We’ll use this file to re-export Table.tsx to simplify import paths.
  • table.css. Contains styles associated with the component. For this tutorial, we’ll use vanilla CSS.
  • Table.tsx. The component itself.

Open Table.tsx and export the following, so that we can verify the component loads when we import it:

<code class="tsx language-tsx"><span class="token keyword">import</span> <span class="token string">'./table.css'</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">Table</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text">Table component</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code>

Inside index.ts, re-export the component using the following line:

<code class="ts language-ts"><span class="token keyword">export</span> <span class="token exports"><span class="token operator">*</span></span> <span class="token keyword">from</span> <span class="token string">'./Table'</span>
</code>

Now that we have the component files set up, let’s verify that it loads by importing it into our app. In this tutorial, we’ll use the App component. If you have an existing React project, you can import it into your desired location. Import the Table component into your app like so:

<code class="tsx language-tsx"><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> <span class="token maybe-class-name">Table</span> <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">'./components/Table'</span>

<span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">App</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Table</span></span> <span class="token punctuation">/></span></span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token maybe-class-name">App</span>
</code>

Generating the mock data

Of course, to work on the table, we’ll need some mock data first. For this tutorial, we can use JSON Generator, a free service for generating random JSON data. We’ll use the following schema to generate the data:

<code class="javascript language-javascript"><span class="token punctuation">[</span>
  <span class="token string">'{{repeat(10)}}'</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>
    id<span class="token operator">:</span> <span class="token string">'{{index()}}'</span><span class="token punctuation">,</span>
    name<span class="token operator">:</span> <span class="token string">'{{firstName()}} {{surname()}}'</span><span class="token punctuation">,</span>
    company<span class="token operator">:</span> <span class="token string">'{{company().toUpperCase()}}'</span><span class="token punctuation">,</span>
    active<span class="token operator">:</span> <span class="token string">'{{bool()}}'</span><span class="token punctuation">,</span>
    country<span class="token operator">:</span> <span class="token string">'{{country()}}'</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">]</span>
</code>

JSON Generator comes with various built-in functionalities to generate different types of data. The above schema will create an array of objects with ten random objects in the form of:

<code class="javascript language-javascript"><span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>                 
  name<span class="token operator">:</span> <span class="token string">'Jaime Wallace'</span><span class="token punctuation">,</span> 
  company<span class="token operator">:</span> <span class="token string">'UBERLUX'</span><span class="token punctuation">,</span>    
  active<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>         
  country<span class="token operator">:</span> <span class="token string">'Peru'</span>        
<span class="token punctuation">}</span>
</code>

Generate a list of entries using the schema above, then create a new file inside the src folder called data.ts and export the array in the following way:

<code class="ts language-ts"><span class="token keyword">export</span> <span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    id<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    name<span class="token operator">:</span> <span class="token string">'Jaime Wallace'</span><span class="token punctuation">,</span>
    company<span class="token operator">:</span> <span class="token string">'UBERLUX'</span><span class="token punctuation">,</span>
    active<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    country<span class="token operator">:</span> <span class="token string">'Peru'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code>

Open App.tsx, and pass this data to the Table component as a prop called rows. We’ll generate the table based on this data:

<code class="diff language-diff"><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> import { Table } from './components/Table'
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> import { data } from './data'
</span></span>
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> const App = () => {
</span><span class="token prefix unchanged"> </span><span class="token line">   return (
</span></span><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line">     <Table />
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">     <Table rows={data} />
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line">   )
</span><span class="token prefix unchanged"> </span><span class="token line"> }
</span></span>
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> export default App
</span></span></code>

Creating the Component

Now that we have both the component and data set up, we can start working on the table. To dynamically generate the table based on the passed data, replace everything in the Table component with the following lines of code:

<code class="tsx language-tsx"><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> useState <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">'react'</span>

<span class="token keyword">import</span> <span class="token string">'./table.css'</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">Table</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> rows <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span>sortedRows<span class="token punctuation">,</span> setRows<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span>rows<span class="token punctuation">)</span>

  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tr</span><span class="token punctuation">></span></span><span class="token plain-text">
          </span><span class="token punctuation">{</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">keys</span><span class="token punctuation">(</span>rows<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>th</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>entry<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>th</span><span class="token punctuation">></span></span>
          <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tr</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token punctuation">{</span>sortedRows<span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
          <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tr</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">
            </span><span class="token punctuation">{</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">values</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> columnIndex</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
              <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>td</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>columnIndex<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>entry<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>td</span><span class="token punctuation">></span></span>
            <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
          </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tr</span><span class="token punctuation">></span></span>
        <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>table</span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code>

This will dynamically generate both the table headings and cells based on the rows prop. Let’s break down how it works. As we’re going to sort and filter the rows, we need to store it in a state using the useState hook. The prop is passed as the initial value to the hook.

To display the table headings, we can use Object.keys on the first entry in the array, which will return the keys of the object as a list of strings:

<code class="javascript language-javascript"><span class="token keyword">const</span> rows <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    id<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    name<span class="token operator">:</span> <span class="token string">'Jaime Wallace'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span>
<span class="token punctuation">]</span>


<span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">keys</span><span class="token punctuation">(</span>rows<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token string">'id'</span><span class="token punctuation">,</span> <span class="token string">'name'</span><span class="token punctuation">]</span>


<span class="token punctuation">[</span><span class="token string">'id'</span><span class="token punctuation">,</span> <span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span><span class="token spread operator">...</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code>

To display the table cells, we need to use Object.values on each row, which returns the value of each key in an object, as opposed to Object.keys. In detail, this is how we display table cells:

<code class="javascript language-javascript"><span class="token keyword">const</span> sortedRows <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    id<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    name<span class="token operator">:</span> <span class="token string">'Jaime Wallace'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span>
<span class="token punctuation">]</span>


<span class="token punctuation">{</span>sortedRows<span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span><span class="token operator"><</span>tr key<span class="token operator">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span><span class="token operator">></span><span class="token spread operator">...</span><span class="token operator"><</span><span class="token operator">/</span>tr<span class="token operator">></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span>


<span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">values</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'Jaime Wallace'</span><span class="token punctuation">]</span>
</code>

This approach makes it extremely flexible to use any type of data with our Table component, without having to rewrite the logic. So far, we’ll have the following table created using our component. However, there are some issues with the formatting.

Formatting issue with Table component

Formatting table cells

Right now, the active column is not displayed. This is because the values for those fields are Boolean, and they aren’t printed as strings in JSX. To resolve this issue, we can introduce a new function for formatting entries based on their values. Add the following to the Table component and wrap entry into the function in the JSX:

<code class="tsx language-tsx"><span class="token keyword">const</span> <span class="token function-variable function">formatEntry</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">entry<span class="token operator">:</span> string <span class="token operator">|</span> number <span class="token operator">|</span> boolean</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> entry <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> entry <span class="token operator">?</span> <span class="token string">'✅'</span> <span class="token operator">:</span> <span class="token string">'❌'</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> entry
<span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token punctuation">(</span>
  <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token punctuation">{</span>sortedRows<span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tr</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">
          </span><span class="token punctuation">{</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">values</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> columnIndex</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>td</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>columnIndex<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token function">formatEntry</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>td</span><span class="token punctuation">></span></span>
          <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tr</span><span class="token punctuation">></span></span>
      <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">
  </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>table</span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span>
</code>

The formatEntry function expects an entry, which in our case can be either string, number, or boolean, and then returns a formatted value if the typeof entry is a boolean, meaning for true values, we’ll display a green checkmark, and for false values, we’ll display a red cross. Using a similar approach, we can also format the table headings. Let’s make them capitalized with the following function:

<code class="ts language-ts"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">capitalize</span> <span class="token operator">=</span> <span class="token punctuation">(</span>
  str<span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">)</span> <span class="token arrow operator">=></span> str<span class="token operator">?.</span><span class="token method function property-access">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\b\w</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> substr <span class="token arrow operator">=></span> substr<span class="token punctuation">.</span><span class="token method function property-access">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code>

This function uses a regex to grab the first letter from each word and turn it into uppercase. To use this function, we can create a utils.ts file at the root of the src folder, export this function, then import it into our Table component to use in the following way:

<code class="tsx language-tsx"><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> capitalize <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">'../../utils'</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">Table</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> rows <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
  <span class="token spread operator">...</span>

  <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">
          </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tr</span><span class="token punctuation">></span></span><span class="token plain-text">
            </span><span class="token punctuation">{</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">keys</span><span class="token punctuation">(</span>rows<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
              <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>th</span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token function">capitalize</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>th</span><span class="token punctuation">></span></span>
            <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
          </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tr</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>thead</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tbody</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>table</span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code>

Based on these modifications, we now have a dynamically built, formatted table.

Formatted table in React

Typing props

Before we jump into styling the table and then adding controls, let’s properly type the rows prop. For this, we can create a types.ts file at the root of the src folder and export custom types that can be reused throughout the project. Create the file and export the following type:

<code class="ts language-ts"><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name"><span class="token maybe-class-name">Data</span></span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    id<span class="token operator">:</span> <span class="token builtin">number</span>
    name<span class="token operator">:</span> <span class="token builtin">string</span>
    company<span class="token operator">:</span> <span class="token builtin">string</span>
    active<span class="token operator">:</span> <span class="token builtin">boolean</span>
    country<span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
</code>

To type the rows prop in the Table component, simply import this type and pass it to the component in the following way:

<code class="tsx language-tsx"><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> <span class="token maybe-class-name">Data</span> <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">'../../types'</span>

<span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name"><span class="token maybe-class-name">TableProps</span></span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  rows<span class="token operator">:</span> <span class="token maybe-class-name">Data</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">Table</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> rows <span class="token punctuation">}</span><span class="token operator">:</span> <span class="token maybe-class-name">TableProps</span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span>
</code>

Styling the Table

To style the entire table component, we’ll only need a couple of rules. First, we want to set the colors and borders, which we can do using the following styles:

<code class="css language-css"><span class="token selector">table</span> <span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">100</span><span class="token unit">%</span><span class="token punctuation">;</span>
  <span class="token property">border-collapse</span><span class="token punctuation">:</span> collapse<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">thead</span> <span class="token punctuation">{</span>
  <span class="token property">text-align</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span> 
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token hexcode color">#939393</span><span class="token punctuation">;</span>
  <span class="token property">background</span><span class="token punctuation">:</span> <span class="token hexcode color">#2f2f2f</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">th<span class="token punctuation">,</span>td</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">4</span><span class="token unit">px</span> <span class="token number">6</span><span class="token unit">px</span><span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token unit">px</span> solid <span class="token hexcode color">#505050</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code>

Add the above to table.css. Make sure to set border-collapse to collapse on the

to avoid double borders. As the table spans the entire screen, let’s also make some adjustments and remove the left and right border, as they aren’t visible anyway:
<code class="css language-css"><span class="token selector">th<span class="token pseudo-class">:first-child</span><span class="token punctuation">,</span>
td<span class="token pseudo-class">:first-child</span></span> <span class="token punctuation">{</span>
  <span class="token property">border-left</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">th<span class="token pseudo-class">:last-child</span><span class="token punctuation">,</span>
th<span class="token pseudo-class">:last-child</span></span> <span class="token punctuation">{</span>
  <span class="token property">border-right</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code>

This will get rid of the borders on each side of the

, resulting in a cleaner look. Lastly, let’s add a hover effect to the table rows to aid users visually when searching the table:
<code class="css language-css"><span class="token selector">tr<span class="token pseudo-class">:hover</span></span> <span class="token punctuation">{</span>
  <span class="token property">background</span><span class="token punctuation">:</span> <span class="token hexcode color">#2f2f2f</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code>

With everything so far, we now have the following behavior for the component.

Table hover effect

Adding Controls

Now that we’ve styled the table, let’s add the controls for the sort and filter functionality. We’ll create an for the filter and a element for the sort. We’ll also include a button for switching between sort orders (ascending/descending).

Table with filter options

To add the inputs, we’ll also need new states for the current order (ascending or descending) and a variable to keep track of the sort key (which key in the object is used for sorting). With that in mind, extend the Table component with the following:

<code class="tsx language-tsx"><span class="token keyword">const</span> <span class="token punctuation">[</span>order<span class="token punctuation">,</span> setOrder<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">'asc'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>sortKey<span class="token punctuation">,</span> setSortKey<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">keys</span><span class="token punctuation">(</span>rows<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> <span class="token function-variable function">filter</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event<span class="token operator">:</span> <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">ChangeEvent</span></span><span class="token operator"><</span><span class="token maybe-class-name">HTMLInputElement</span><span class="token operator">></span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">const</span> <span class="token function-variable function">sort</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">value<span class="token operator">:</span> keyof <span class="token maybe-class-name">Data</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> order<span class="token operator">:</span> string</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateOrder</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">return</span> <span class="token punctuation">(</span>
  <span class="token tag"><span class="token tag"><span class="token punctuation"><</span></span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>controls<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span>
        <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span>
        <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Filter items<span class="token punctuation">"</span></span>
        <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>filter<span class="token punctuation">}</span></span>
      <span class="token punctuation">/></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token punctuation">{</span><span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">keys</span><span class="token punctuation">(</span>rows<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">entry<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">(</span>
          <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>option</span> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>entry<span class="token punctuation">}</span></span> <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">
            Order by </span><span class="token punctuation">{</span><span class="token function">capitalize</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
          </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>option</span><span class="token punctuation">></span></span>
        <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>updateOrder<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">Switch order (</span><span class="token punctuation">{</span>order<span class="token punctuation">}</span><span class="token plain-text">)</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">
  </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span></span><span class="token punctuation">></span></span>
<span class="token punctuation">)</span>
</code>

Let’s go in order to understand what changed:

  • order. First, we need to create a new state for the sort order. This can be one of asc or desc. We’ll use its value in the sort function.
  • sortKey. We also need a state for the sort key. By default, we can grab the key of the very first property in our array of objects using Object.keys(rows[0])[0]. We’ll use this to keep track of the sort when switching between orders.
  • filter. We’ll need a function for filtering results. This needs to be passed to the onChange event on the element. Note that React.ChangeEvent is a generic and can accept the type of HTML element that triggered the change.
  • sort. Just like the filter function, this will need to be attached to the onChange event, but this time, on the element. It will accept two parameters:
  • value. It can take keys of our data object. We can specify the type using the keyof keyword. It means that value can be one of id, name, company, active, or country.
  • order. The order of the sort, either asc or desc.
  • updateOrder. Lastly, we also need a function for updating the order. This will be triggered on button click.
  • Note that we use the same logic we did for the

    elements for dynamically generating the options for the . We can also reuse the capitalize utility function to format the options.

    Available select options

    Styling controls

    Let’s style the controls before moving forward. This can be done with just a handful of CSS rules. Extend table.css with the following:

    <code class="css language-css"><span class="token selector"><span class="token class">.controls</span></span> <span class="token punctuation">{</span>
      <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token selector">input<span class="token punctuation">,</span>
    select</span> <span class="token punctuation">{</span>
      <span class="token property">flex</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
      <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">5</span><span class="token unit">px</span> <span class="token number">10</span><span class="token unit">px</span><span class="token punctuation">;</span>
      <span class="token property">border</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token selector">button</span> <span class="token punctuation">{</span>
      <span class="token property">background</span><span class="token punctuation">:</span> <span class="token hexcode color">#2f2f2f</span><span class="token punctuation">;</span>
      <span class="token property">color</span><span class="token punctuation">:</span> <span class="token hexcode color">#FFF</span><span class="token punctuation">;</span>
      <span class="token property">border</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">;</span>
      <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>
      <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">5</span><span class="token unit">px</span> <span class="token number">10</span><span class="token unit">px</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    </code>

    This will ensure that inputs are aligned next to each other. By using flex: 1 on the and elements, we can make them take up an equal amount of width from the available space. The will take up as much space as needed for its text.

    Filtering the Table

    Now that we have the controls in place, let’s look at implementing the functionality. For filtering the table based on any field, we’ll need to follow this logic:

    <code class="javascript language-javascript"><span class="token keyword">const</span> rows <span class="token operator">=</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span>
        id<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
        name<span class="token operator">:</span> <span class="token string">'Jaime Wallace'</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
    
    
    
    <span class="token function">setRows</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token spread operator">...</span>rows <span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token method function property-access">filter</span><span class="token punctuation">(</span><span class="token parameter">row</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token spread operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    
    
    
    <span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">values</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'Jaime Wallace'</span><span class="token punctuation">]</span>
    
    
    <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'Jaime Wallace'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token method function property-access">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token string">'0Jaime Wallace'</span>
    
    
    <span class="token string">'0Jaime Wallace'</span><span class="token punctuation">.</span><span class="token method function property-access">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token string">'0jaime wallace'</span>
    
    
    <span class="token string">'0jaime wallace'</span><span class="token punctuation">.</span><span class="token method function property-access">includes</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token boolean">true</span> <span class="token operator">/</span> <span class="token boolean">false</span>
    </code>

    With everything combined, we can create the return value for the filter based on the above logic. This leaves us with the following implementation for the filter function:

    <code class="javascript language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">filter</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">event<span class="token operator">:</span> <span class="token maybe-class-name">React</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">ChangeEvent</span></span><span class="token operator"><</span><span class="token maybe-class-name">HTMLInputElement</span><span class="token operator">></span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> value <span class="token operator">=</span> event<span class="token punctuation">.</span><span class="token property-access">target</span><span class="token punctuation">.</span><span class="token property-access">value</span>
    
      <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">setRows</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token spread operator">...</span>rows<span class="token punctuation">.</span><span class="token method function property-access">filter</span><span class="token punctuation">(</span><span class="token parameter">row</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword control-flow">return</span> <span class="token known-class-name class-name">Object</span><span class="token punctuation">.</span><span class="token method function property-access">values</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token method function property-access">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token method function property-access">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token method function property-access">includes</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">]</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span> <span class="token keyword control-flow">else</span> <span class="token punctuation">{</span>
        <span class="token function">setRows</span><span class="token punctuation">(</span>rows<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    </code>

    Note that we also want to check if the value is present. Its absence means the field is empty. In such cases, we want to reset the state and pass the unfiltered rows to setRows to reset the table.

    Filtering the table

    Sorting the Table

    We have the filter functionality, but we’re still missing sorting. For sorting, we have two separate functions:

    • sort. The function that will handle sorting.
    • updateOder. The function that will switch the order of sorting from ascending to descending and vice versa.

    Let’s start with the sort function first. Whenever the changes, the sort function will be called. We want to use the value of the element to decide which key to use for sorting. For this, we can use a simple sort method and bracket notation to dynamically compare object keys:

    <code class="javascript language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">sort</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">value<span class="token operator">:</span> keyof <span class="token maybe-class-name">Data</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> order<span class="token operator">:</span> string</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> returnValue <span class="token operator">=</span> order <span class="token operator">===</span> <span class="token string">'desc'</span> <span class="token operator">?</span> <span class="token number">1</span> <span class="token operator">:</span> <span class="token operator">-</span><span class="token number">1</span>
    
      <span class="token function">setSortKey</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
      <span class="token function">setRows</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token spread operator">...</span>sortedRows<span class="token punctuation">.</span><span class="token method function property-access">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword control-flow">return</span> a<span class="token punctuation">[</span>value<span class="token punctuation">]</span> <span class="token operator">></span> b<span class="token punctuation">[</span>value<span class="token punctuation">]</span>
          <span class="token operator">?</span> returnValue <span class="token operator">*</span> <span class="token operator">-</span><span class="token number">1</span>
          <span class="token operator">:</span> returnValue
      <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    </code>

    Let’s go through the function from top to bottom to better understand the implementation.

    • returnValue. Based on the order state, we want the return value to be either 1 or -1. This helps us define the sort order (1 for descending and -1 for ascending).
    • setSortKey. The value passed to the function is the value of the element. We want to record this value in our state (sortKey), which we can do by calling the setSortKey updater function.
    • setRows. The actual sorting happens in this call. Using bracket notation, we can compare a[value] with b[value] and return either -1 or 1.

    Let’s take the following as an example:

    <code class="javascript language-javascript"><span class="token keyword">const</span> rows <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">]</span>
    <span class="token keyword">const</span> value <span class="token operator">=</span> <span class="token string">'id'</span>
    
    
    rows<span class="token punctuation">.</span><span class="token method function property-access">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> a<span class="token punctuation">[</span>value<span class="token punctuation">]</span> <span class="token operator">></span> b<span class="token punctuation">[</span>value<span class="token punctuation">]</span> <span class="token operator">?</span> <span class="token operator">-</span><span class="token number">1</span> <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    
    
    rows<span class="token punctuation">.</span><span class="token method function property-access">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> a<span class="token punctuation">[</span>value<span class="token punctuation">]</span> <span class="token operator">></span> b<span class="token punctuation">[</span>value<span class="token punctuation">]</span> <span class="token operator">?</span> <span class="token number">1</span> <span class="token operator">:</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
    </code>

    Switching between sort orders

    To update the sort order, we just need to update the order state whenever the button is clicked. We can achieve this with the following functionality:

    <code class="javascript language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">updateOrder</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> updatedOrder <span class="token operator">=</span> order <span class="token operator">===</span> <span class="token string">'asc'</span> <span class="token operator">?</span> <span class="token string">'desc'</span> <span class="token operator">:</span> <span class="token string">'asc'</span>
    
      <span class="token function">setOrder</span><span class="token punctuation">(</span>updatedOrder<span class="token punctuation">)</span>
      <span class="token function">sort</span><span class="token punctuation">(</span>sortKey <span class="token keyword module">as</span> keyof <span class="token maybe-class-name">Data</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> updatedOrder<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    </code>

    It’ll set the order to its opposite on each click. Note that after we update the order state using setOrder, we also need to call the sort function to resort the table based on the updated order. To infer the correct type for the sortKey variable, we can reference the keys of the Data type using typecasting: as keyof Data[0]. As the second parameter, we also need to pass the updated order.

    Ordering the table

    Handling Overfiltering

    To complete this project, let’s add some indication for an overfiltered state. We only want to show an overfiltered state if there are no results. This can be easily done by checking the length of our sortedRows state. After the

    element, add the following:
    <code class="tsx language-tsx"><span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token tag"><span class="token tag"><span class="token punctuation"><</span></span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>controls<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>table</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token punctuation">{</span><span class="token operator">!</span>sortedRows<span class="token punctuation">.</span><span class="token property-access">length</span> <span class="token operator">&&</span> <span class="token punctuation">(</span>
          <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text">No results... Try expanding the search</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
        <span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span></span><span class="token punctuation">></span></span>
    <span class="token punctuation">)</span>
    </code>

    Overfiltered state

    Conclusion

    In conclusion, building a sortable and filterable table in React doesn’t have to be complicated. With array methods and function chaining, using the right functionality, we can create concise and precise functions for handling these tasks. With everything included, we managed to fit the entire logic into less than 100 lines of code.

    As seen at the beginning of this tutorial, the entire project is available in one piece on GitHub. Thank you for reading through; happy coding!

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Back to top button
    WP Twitter Auto Publish Powered By : XYZScripts.com
    SiteLock