DEV Community

Richard Beattie
Richard Beattie

Posted on • Originally published at r-bt.com

4 2

React Table useGlobalFilter with two columns

This week I needed to filter a table made with React Table. React table is great for its extensibility and so has hooks for this: useFilters and useGlobalFilter. useFilter is for filtering by an individual column and useGlobalFilter for filtering by content in any column.

However I needed to filter two columns by a single input. My table is for ingredients and has columns for: code, name, price per unit, supplier, etc. I need to filter by name and code. I couldn't use useFilters as that would do an intersection (i.e. the search query would need to be in both the code and name row).

See the end Code Sandbox at: https://codesandbox.io/s/fuzzy-text-global-filter-rcy1f?file=/src/Table.tsx

Filtering Ingredients on Prepsheets.com

Filtering Prepsheets.com Ingredients by Code

Thankfully, it's possible to do this with useGlobalFilter.



import { 
    ..., 
    useGlobalFilter,
} from 'react-table'

...

const {
    ...,
    setGlobalFilter,
} = useTable(
    {
        ...
    },
    ...
    useGlobalFilter,
);


Enter fullscreen mode Exit fullscreen mode

See Code Sandbox: https://codesandbox.io/s/all-columns-global-filter-buof9?file=/src/Table.tsx

Awesome, by using setGlobalFilter we can now filter by the content in any column. To restrict which columns we filter we'll specify a custom globalFilter function.



import {
    ...
    useGlobalFilter,
    Row, // Typescript
    IdType, // Typescript
}
import React, { ..., useCallback } = 'react'

...

const ourGlobalFilterFunction = useCallback(
    // This is Typescript if you're using JS remove the types (e.g. :string)
    (rows: Row<T>[], ids: IdType<T>[], query: string) => {
        return rows.filter((row) => 
            row.values['code'].includes(query) ||
            row.values['name'].includes(query)
        );
    },
    [],
);

const {
    ...
    setGlobalFilter,
} = useTable(
    {
        globalFilter: ourGlobalFilterFunction
    },
    ...
    useGlobalFilter,
);


Enter fullscreen mode Exit fullscreen mode

See Code Sandbox: https://codesandbox.io/s/specific-columns-global-filter-n1k4v?file=/src/Table.tsx

However, in my case this is inside a Table component which I use in a couple of places, so let's make ourGlobalFilterFunction take arbitrary column names for filtering. We'll also pass the filter query as a prop to Table.



interface TableProps {
    filters: string[];
    filter: string;
}

const Table: React.FC<TableProps> = ({
    filters,
    filter,
}): React.ReactComponent => {

    const ourGlobalFilterFunction = useCallback(
        // This is Typescript if you're using JS remove the types (e.g. :string)
        (rows: Row<T>[], ids: IdType<T>[], query: string) => {
            return rows.filter((row) => 
                for (const filter of filters) {
                    return row.values[filter].includes(query)
                }
            );
        },
        [filters],
    );

    const {
      ...
      setGlobalFilter,
    } = useTable(
        {
            globalFilter: ourGlobalFilterFunction
        },
        ...
        useGlobalFilter,
    );

    useEffect(() => {
        setGlobalFilter(filter) // Set the Global Filter to the filter prop.
    }, [filter, setGlobalFilter]);

    return (
        ...
    );
}


Enter fullscreen mode Exit fullscreen mode

Code Sandbox: https://codesandbox.io/s/filter-props-global-filter-i18bd?file=/src/Table.tsx

Finally, I'd like this to do fuzzy text filtering. We'll use the match-sorter library for this



npm install match-sorter


Enter fullscreen mode Exit fullscreen mode


import { matchSorter } from 'match-sorter';

...

const globalFilter = useCallback(
    (rows: Row<T>[], ids: IdType<T>[], query: string) => {
        return matchSorter(rows, query, {
            keys: filters.map((columnName) => `values.${columnName}`),
        });
    },
    [filters],
);


Enter fullscreen mode Exit fullscreen mode

Code Sandbox: https://codesandbox.io/s/fuzzy-text-global-filter-rcy1f?file=/src/Table.tsx

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (1)

Collapse
 
anurella profile image
Anurella

Thank you for this

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay