TanStack / table

🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
https://tanstack.com/table
MIT License
24.55k stars 3.03k forks source link

'Property filterFns is missing' using useReactTable #5005

Open mdodge-ecgrow opened 11 months ago

mdodge-ecgrow commented 11 months ago

Describe the bug

This is probably not a bug, but I cannot figure out why my useReactTable call is saying that the filterFns property is required. This is the code where all the red squigglies are:

const table = useReactTable({
    data: users,
    columns,
    getCoreRowModel: getCoreRowModel()
});

Full error: image

And here is my full component:

import React, { useState } from 'react';
import {
    ColumnDef,
    createColumnHelper,
    flexRender,
    getCoreRowModel,
    useReactTable
} from '@tanstack/react-table';
import { Scrollbars } from 'rc-scrollbars';

type User = {
    name: string;
    email: string;
    role: string;
};

const columnHelper = createColumnHelper<User>();

const columns: ColumnDef<User, string>[] = [
    columnHelper.accessor((row) => row.name, {
        id: 'name',
        cell: (info) => <i>{info.getValue()}</i>,
        header: () => <span>Name</span>
    }),
    columnHelper.accessor((row) => row.email, {
        id: 'email',
        cell: (info) => <i>{info.getValue()}</i>,
        header: () => <span>Email</span>
    }),
    columnHelper.accessor((row) => row.role, {
        id: 'role',
        cell: (info) => <i>{info.getValue()}</i>,
        header: () => <span>Role</span>
    })
];

type UserTableProps = {
    users: Array<User>;
    selectedUser: User;
    showUserManagement: Function;
};

const UsersTable = (props: UserTableProps) => {
    const { users, selectedUser, showUserManagement } = props;

    console.log({ users });

    const table = useReactTable({
        data: users,
        columns,
        getCoreRowModel: getCoreRowModel()
    });

    const [showUserCheckID, setShowUserCheckID] = useState(-1);

    const setTheSelectedUser = (
        e: React.MouseEvent<HTMLTableRowElement>,
        email: string
    ) => {
        e.preventDefault();
        console.log({ email });
        const selectedUser = users.find((u) => u.email === email);
        showUserManagement(selectedUser);
    };

    // const thumbVertical = ({ style, ...props }) => {
    //  console.log(typeof style);
    //  const finalStyle = {
    //      ...style,
    //      visibility: 'hidden'
    //  };
    //
    //  return <div style={finalStyle} {...props} />;
    // };

    return (
        <div className={'table-container'}>
            <Scrollbars
                autoHeight
                autoHeightMin={0}
                autoHeightMax={'calc(100vh - 40px)'}
                // renderThumbVertical={thumbVertical}
            >
                <table
                    className={
                        'table table-striped table-hover table-borderless'
                    }
                >
                    <thead>
                        {table.getHeaderGroups().map((headerGroup) => (
                            <tr key={headerGroup.id}>
                                {headerGroup.headers.map((header) => (
                                    <th key={header.id}>
                                        {header.isPlaceholder
                                            ? null
                                            : flexRender(
                                                    header.column.columnDef.header,
                                                    header.getContext()
                                              )}
                                    </th>
                                ))}
                            </tr>
                        ))}
                    </thead>
                    <tbody>
                        {table.getRowModel().rows.map((row) => (
                            <tr
                                key={row.id}
                                onClick={(e) =>
                                    setTheSelectedUser(e, row.getValue('email'))
                                }
                            >
                                {row.getVisibleCells().map((cell) => (
                                    <td key={cell.id}>
                                        {flexRender(
                                            cell.column.columnDef.cell,
                                            cell.getContext()
                                        )}
                                    </td>
                                ))}
                            </tr>
                        ))}
                    </tbody>
                </table>
            </Scrollbars>
        </div>
    );
};

export default UsersTable;

Your minimal, reproducible example

https://codesandbox.io/s/keen-aj-lxqrw8?file=/src/UsersTable.tsx

Steps to reproduce

Create the table with the following code:

const table = useReactTable({
    data: users,
    columns,
    getCoreRowModel: getCoreRowModel()
});

Expected behavior

It should create the table and not throw any typescript errors about requiring 'filterFns'.

How often does this bug happen?

Every time

Screenshots or Videos

image

image

Platform

OS: Windows 11 Pro Browser: Firefox 115.0.3 64 bit

react-table version

8.9.3

TypeScript version

5.1.6

Additional context

I noticed in my sandbox example, there are no Typescript errors. So I'm not sure if it is something related to my IDE? I am using Webstorm 2023.2.

Terms & Code of Conduct

mdodge-ecgrow commented 11 months ago

This is frustrating because, on this page: https://tanstack.com/table/v8/docs/api/core/table#usereacttable--createsolidtable--usevuetable--createsveltetable I searched for the term "filterFns" and got zero hits. So I have no idea why I am getting a typescript error saying that parameter is required.

vrushank commented 11 months ago

Facing the same issue here. I'm using Next.js with pnpm. If that has something to do with this issue. 🤔

As @mdodge-ecgrow has mentioned, not defining "filterFns" throws typescript error.

Relaximus commented 10 months ago

Had the same problem. I looked in the code and found this in Filters.ts:

type ResolvedFilterFns = keyof FilterFns extends never
  ? {
      filterFns?: Record<string, FilterFn<any>>
    }
  : {
      filterFns: Record<keyof FilterFns, FilterFn<any>>
    }

So I've checked if somewhere exists FilterFns implementations in the code, cleaned them out - and these exceptions disappeared.

kubacichorski commented 9 months ago

Not sure if this helps, but we had the same error appear when we merged two branches, where each had a different table. One without filterFns defined worked fine before merge. After merge, it started complaining.

Turned out one of our devs added this piece of code to make the table filterable:

declare module '@tanstack/table-core' {
  interface FilterFns { fuzzy: FilterFn<unknown> }
  interface FilterMeta { itemRank: RankingInfo }
}

I'm 99% sure it was copied from Table filter examples (from main.tsx) here: https://tanstack.com/table/v8/docs/examples/react/filters

I'm also 99% sure it is not needed for filtering to work.

AdirTrichter commented 8 months ago

@kubacichorski I must say that I think that you are incorrect and it is required, because I have this declaration in my code too and without it where you configure your columns and relate to a custom filter that you define, it shows a typescript error: Type '"fuzzy"' is not assignable to type FilterFnOptions<RowType>

Yes it might not be required for the tables filters to work but it does required by TS for dealing with these errors.

@Relaximus didn't you break any existing logic that was originally implemented by deleting these implementations for filterFns?

Related to this thread, I noticed this error shows to me when I tried to create a second table that shouldn't have custom filterFn, does anyone here know if it's possible to override a declared module?

christinachimi commented 4 months ago

I had the same issue, even when putting the declare in the file with the table I wanted to filter on (not in any shared code), which I guess makes sense. Defining the filters inline works, you just don't get the brevity of a named filter.

ROD-MASAMI commented 3 months ago

@AdirTrichter i have the same issue when deifing a custom filter how do i solve it i'm getting this error

Type '"myCustomFilterFn"' is not assignable to type 'FilterFnOption | undefined'.ts

djshubs commented 3 months ago

I am facing the same problem.

ROD-MASAMI commented 3 months ago

@djshubs i ended up writing the function on all columns that i need it until i find out how to solve it

luap2703 commented 2 months ago

@djshubs i ended up writing the function on all columns that i need it until i find out how to solve it

Have you tried this? Makes sure filterFns stays optional.

declare module "@tanstack/table-core" {
  interface TableOptions<TData extends RowData>
    extends PartialKeys<TableOptionsResolved<TData>, "state" | "onStateChange" | "renderFallbackValue"> {
    filterFns?: FilterFns;
  }

  interface FilterFns {
    "=": FilterFn<unknown>;
    contains: FilterFn<unknown>;
    yourCustomFunction: FilterFn<unknown>
  }
}