'React-Table with typescript filtering outside of table component

Hello I am currently working on a project with React-table and typescript however I cant seem to make the custom filter work, the custom filter should work outside the table, I've added types that I have found, but can't seem to make it work, I keep getting cannot read foreach of undefined even though I have the data

enter image description here enter image description here

table Component 
/* eslint-disable react/no-array-index-key */
import Image from 'next/image';
import { Text } from '@/ui';
import { UserActivities } from '@/types/user-types';
import { useEffect, useMemo, useState } from 'react';
import { useTable, useFilters } from 'react-table';

import Link from 'next/link';
import { DropDown, Icon } from '..';
import TableFilter from '../dropdown/table-filter';

interface Props {
  title: string;
  activities?: UserActivities;
}
const DropDownOneOptions = [
  {
    label: 'All',
    value: 'ALL',
  },
  {
    label: 'Last 24 hours',
    value: 'Last 24 hours',
  },
  {
    label: 'Last 7 Days',
    value: 'Last 7 Days',
  },
  {
    label: 'Last 30 Days',
    value: 'Last 30 Days',
  },
  {
    label: 'Last 90 Days',
    value: 'Last 90 Days',
  },
];

// TODO his needs to be refactored extremely bad to do it like this

const customFilterFunction = (rows: any, id: any, filterValue: any) => {
  console.log({ rows, id, filterValue });
  if (filterValue === 'ALL') {
    return rows;
  }
  if (filterValue === 'Last 24 hours') {
    return rows.filter((row) => {
      const date = new Date(row.original.date);
      const currentDate = new Date();
      const diffTime = Math.abs(currentDate.getTime() - date.getTime());
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      return diffDays <= 1;
    });
  }
  if (filterValue === 'Last 7 Days') {
    return rows.filter((row) => {
      const date = new Date(row.original.date);
      const currentDate = new Date();
      const diffTime = Math.abs(currentDate.getTime() - date.getTime());
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      return diffDays <= 7;
    });
  }
  if (filterValue === 'Last 30 Days') {
    return rows.filter((row) => {
      const date = new Date(row.original.date);
      const currentDate = new Date();
      const diffTime = Math.abs(currentDate.getTime() - date.getTime());
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      return diffDays <= 30;
    });
  }
  if (filterValue === 'Last 90 Days') {
    return rows.filter((row) => {
      const date = new Date(row.original.date);
      const currentDate = new Date();
      const diffTime = Math.abs(currentDate.getTime() - date.getTime());
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      return diffDays <= 90;
    });
  }
};

const UserTable = ({ title, activities }: Props) => {
  const [filterDays, setFilterDays] = useState(DropDownOneOptions[0].label);

  const data = useMemo(
    // check if the activities is empty
    () =>
      activities
        ? activities.activities?.map((activity) => ({
            ...activity,
          }))
        : [],
    [activities]
  );

  const columns = useMemo(
    (): any => [
      {
        Header: 'Event',
        accessor: 'event',
        // filters
      },
      {
        Header: 'Item',
        accessor: 'item',
        Cell: ({ cell: { value } }: any) => (
          <div className="flex gap-[12px]">
            <div className="w-[45px] h-[45px] rounded-[10px]">
              <Link href={`/${value?.token_id}?${value?.contract}`}>
                <a>
                  <Image
                    src={value ? value.image_path : 'https://i.pravatar.cc/300'}
                    width={45}
                    height={45}
                    className="rounded-[10px]"
                  />
                </a>
              </Link>
            </div>
            <div>
              <Text>{value.nickname || 'Very Smart'}</Text>
              <Text size="sm" variant="primary">
                {' '}
                {value.token_id || 2}
              </Text>
            </div>
          </div>
        ),
      },
      {
        Header: 'Price',
        accessor: 'price',
        Cell: ({ cell: { value } }: any) =>
          value ? (
            <div className="flex items-center ">
              <Icon src="/eths.svg" width={15} height={16} className="mr-1" />
              <Text className="text-lg font-bold">{value}</Text>
            </div>
          ) : null,
      },
      // from is an object that contains username and owner_address
      {
        Header: 'From',
        accessor: 'from',
        Cell: ({ cell: { value } }: any) => (
          <Link href={`/homepage/${value.owner_address}`}>
            <a>
              <Text size="sm" variant="accent">
                {value.username || 'from un is here'}
              </Text>
            </a>
          </Link>
        ),
      },
      // to is an object that contains username and owner_address
      {
        Header: 'To',
        accessor: 'to',
        Cell: ({ cell: { value } }: any) => (
          <Link href={`/homepage/${value.owner_address}`}>
            <a>
              <Text size="sm" variant="accent">
                {value.username || 'from un is here'}
              </Text>
            </a>
          </Link>
        ),
      },
      {
        Header: 'Date',
        accessor: 'date_tag',
        Cell: ({ cell: { value } }: any) => <Text size="sm">{value}</Text>,
        filter: customFilterFunction,
      },
    ],
    []
  );

  const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, setFilter } =
    useTable({ columns, data }, useFilters);

  // console.log(setFilter());
  useEffect(() => {
    if (activities) {
      setFilter('date_tag', filterDays);
    }
  }, [filterDays]);

  return (
    <div className="flex flex-col mt-[25px] bg-[#1E1E1E] p-[50px] rounded-m-round">
      <div className="justify-between items-center grid grid-cols-3">
        <Text variant="accent" size="3xl" className="col-span-2">
          {title}
        </Text>
        {/*  */}
        <TableFilter
          options={DropDownOneOptions}
          filterDay={filterDays}
          setFilterDays={setFilterDays}
        />
      </div>
      {/* table Starts here */}
      <div className="w-full  h-[1050px] overflow-y-auto no-scrollbar gap-5">
        <table className="w-full  mt-12 border-collapse">
          <thead>
            {headerGroups.map((headerGroup, i) => {
              const { key, ...restHeaderGroupProps } = headerGroup.getHeaderGroupProps();
              return (
                <tr key={key} {...restHeaderGroupProps}>
                  {headerGroup.headers.map((column, i) => {
                    const { key, ...restColumn } = column.getHeaderProps();

                    return (
                      <th
                        key={key}
                        {...restColumn}
                        className="text-lg text-white/50 text-left pr-4"
                      >
                        {column.render('Header')}
                      </th>
                    );
                  })}
                </tr>
              );
            })}
          </thead>
          <tbody {...getTableBodyProps()}>
            {rows.map((row) => {
              prepareRow(row);
              const { key, ...restRowProps } = row.getRowProps();
              return (
                <tr key={key} {...restRowProps}>
                  {row.cells.map((cell) => {
                    const { key, ...restCellProps } = cell.getCellProps();
                    return (
                      <td
                        key={key}
                        {...restCellProps}
                        className="pt-[30px] pb-5  whitespace-nowrap text-sm text-white text-left capitalize"
                      >
                        {cell.render('Cell')}
                      </td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default UserTable;


filter component

import { Listbox } from '@headlessui/react';
import clsx from 'clsx';
import { Fragment, useState } from 'react';

interface Props {
  options: {
    label: string;
    value: string;
  }[];
  filterDay: any;
  setFilterDays: any;
}

const TableFilter = ({ options, filterDay, setFilterDays }: Props) => {
  // const [selectedItem, setSelectedItem] = useState('this is');
  const handleChange = (e: any) => {
    setFilterDays(e.value);
  };

  return (
    <Listbox
      as="div"
      value={filterDay}
      onChange={handleChange}
      className="relative inline-block text-left col-start-4 z-10"
    >
      <Listbox.Button
        className="rounded-[10px] flex justify-between border text-white border-white/60 shadow-sm px-[15px] py-[18px]   focus:outline-none focus:ring-1 focus:ring-offset-1 focus:ring-offset-gray-100 focus:ring-mgreen hover:border-mgreen  w-[223px] max-w-[223px]
      "
      >
        {filterDay}
        <svg
          className="mr-1 ml-2 h-5 w-5"
          fill="none"
          stroke="currentColor"
          viewBox="0 0 24 24"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M19 9l-7 7-7-7"
          />
        </svg>
      </Listbox.Button>
      <Listbox.Options className="origin-top-right absolute right-0 mt-[15px] w-56 shadow-lg bg-black ring-1 ring-black ring-opacity-5 focus:outline-none rounded-[10px] ">
        <div className="py-1">
          {options.map((option) => (
            <Listbox.Option key={option.label} value={option} as={Fragment}>
              {({ active, selected }) => (
                <li
                  className={clsx(
                    active ? 'bg-mgreen text-black' : 'text-white text-sm',
                    'block px-4 py-2 text-sm'
                  )}
                >
                  {option.label}
                </li>
              )}
            </Listbox.Option>
          ))}
        </div>
      </Listbox.Options>
    </Listbox>
  );
};

export default TableFilter;


types I have used in global

/* eslint-disable no-use-before-define */
// Type definitions for react-table 7
// Project: https://github.com/tannerlinsley/react-table#readme
// Definitions by: Adrien Denat <https://github.com/grsmto>
//                 Artem Berdyshev <https://github.com/berdyshev>
//                 Christian Murphy <https://github.com/ChristianMurphy>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.0

import { Dispatch, SetStateAction, ReactNode } from 'react';
import {
  TableInstance,
  UseColumnOrderInstanceProps,
  UseColumnOrderState,
  UseExpandedHooks,
  UseExpandedInstanceProps,
  UseExpandedOptions,
  UseExpandedRowProps,
  UseExpandedState,
  UseFiltersColumnOptions,
  UseFiltersColumnProps,
  UseFiltersInstanceProps,
  UseFiltersOptions,
  UseFiltersState,
  UseGlobalFiltersInstanceProps,
  UseGlobalFiltersOptions,
  UseGlobalFiltersState,
  UseGroupByCellProps,
  UseGroupByColumnOptions,
  UseGroupByColumnProps,
  UseGroupByHooks,
  UseGroupByInstanceProps,
  UseGroupByOptions,
  UseGroupByRowProps,
  UseGroupByState,
  UsePaginationInstanceProps,
  UsePaginationOptions,
  UsePaginationState,
  UseResizeColumnsColumnOptions,
  UseResizeColumnsColumnProps,
  UseResizeColumnsOptions,
  UseResizeColumnsState,
  UseRowSelectHooks,
  UseRowSelectInstanceProps,
  UseRowSelectOptions,
  UseRowSelectRowProps,
  UseRowSelectState,
  UseSortByColumnOptions,
  UseSortByColumnProps,
  UseSortByHooks,
  UseSortByInstanceProps,
  UseSortByOptions,
  UseSortByState,
} from 'react-table';

declare module 'react-table' {
  export interface Cell<D> {
    render: (type: string) => any;
    getCellProps: () => any;
    row: Row<D>;
    column: Column<D>;
    state: any;
    value: any;
  }

  export interface Row<D> {
    index: number;
    cells: Cell<D>[];
    getRowProps: () => any;
    original: any;
  }

  export interface HeaderColumn<D, A extends keyof D = never> {
    /**
     * This string/function is used to build the data model for your column.
     */
    accessor: A | ((originalRow: D) => string);
    Header?: string | ((props: TableInstance<D>) => ReactNode);
    Filter?: string | ((props: TableInstance<D>) => ReactNode);
    Cell?: string | ((cell: Cell<D>) => ReactNode);

    /**
     * This is the unique ID for the column. It is used by reference in things like sorting, grouping, filtering etc.
     */
    id?: string | number;
    minWidth?: string | number;
    maxWidth?: string | number;
    width?: string | number;
    canSortBy?: boolean;
    sortByFn?: (a: any, b: any, desc: boolean) => 0 | 1 | -1;
    defaultSortDesc?: boolean;
  }

  export interface Column<D, A extends keyof D = never> extends HeaderColumn<D, A> {
    id: string | number;
  }

  export type Page<D> = Row<D>[];

  export interface EnhancedColumn<D, A extends keyof D = never> extends Column<D, A> {
    render: (type: string) => any;
    getHeaderProps: (userProps?: any) => any;
    getSortByToggleProps: (userProps?: any) => any;
    sorted: boolean;
    sortedDesc: boolean;
    sortedIndex: number;
  }

  export type HeaderGroup<D, A extends keyof D = never> = {
    headers: EnhancedColumn<D, A>[];
    getRowProps: (userProps?: any) => any;
  };

  export interface Hooks<D> {
    beforeRender: [];
    columns: [];
    headerGroups: [];
    headers: [];
    rows: Row<D>[];
    row: [];
    renderableRows: [];
    getTableProps: [];
    getRowProps: [];
    getHeaderRowProps: [];
    getHeaderProps: [];
    getCellProps: [];
  }

  export interface TableInstance<D>
    extends TableOptions<D>,
      UseRowsValues<D>,
      UseFiltersValues,
      UsePaginationValues<D>,
      UseColumnsValues<D> {
    hooks: Hooks<D>;
    rows: Row<D>[];
    columns: EnhancedColumn<D>[];
    getTableProps: (userProps?: any) => any;
    getRowProps: (userProps?: any) => any;
    prepareRow: (row: Row<D>) => any;
    getSelectRowToggleProps: (userProps?: any) => any;
    toggleSelectAll: (forcedState: boolean) => any;
  }

  export interface TableOptions<D> {
    data: D[];
    columns: HeaderColumn<D>[];
    state?: [any, Dispatch<SetStateAction<any>>];
    debug?: boolean;
    sortByFn?: (a: any, b: any, desc: boolean) => 0 | 1 | -1;
    manualSorting?: boolean;
    disableSorting?: boolean;
    defaultSortDesc?: boolean;
    disableMultiSort?: boolean;
  }

  export interface RowsProps {
    subRowsKey: string;
  }

  export interface FiltersProps {
    filterFn: () => void;
    manualFilters: boolean;
    disableFilters: boolean;
    setFilter: (any, any) => any;
    setAllFilters: () => any;
  }

  export interface UsePaginationValues<D> {
    nextPage: () => any;
    previousPage: () => any;
    setPageSize: (size: number) => any;
    gotoPage: (page: number) => any;
    canPreviousPage: boolean;
    canNextPage: boolean;
    page: Page<D>;
    pageOptions: [];
  }

  export interface UseRowsValues<D> {
    rows: Row<D>[];
  }

  export interface UseColumnsValues<D> {
    columns: EnhancedColumn<D>[];
    headerGroups: HeaderGroup<D>[];
    headers: EnhancedColumn<D>[];
  }

  export interface UseFiltersValues {
    setFilter: (any, any) => any;
    setAllFilters: () => any;
  }

  export function useTable<D>(
    props: TableOptions<D>,
    ...plugins: any[]
  ): TableInstance<D>;

  export function useColumns<D>(
    props: TableOptions<D>
  ): TableOptions<D> & UseColumnsValues<D>;

  export function useRows<D>(props: TableOptions<D>): TableOptions<D> & UseRowsValues<D>;

  export function useFilters<D>(props: TableOptions<D>): TableOptions<D> & {
    rows: Row<D>[];
  };

  export function useSortBy<D>(props: TableOptions<D>): TableOptions<D> & {
    rows: Row<D>[];
  };

  export function useGroupBy<D>(
    props: TableOptions<D>
  ): TableOptions<D> & { rows: Row<D>[] };

  export function usePagination<D>(props: TableOptions<D>): UsePaginationValues<D>;

  export function useFlexLayout<D>(props: TableOptions<D>): TableOptions<D>;

  export function useExpanded<D>(props: TableOptions<D>): TableOptions<D> & {
    toggleExpandedByPath: () => any;
    expandedDepth: [];
    rows: [];
  };

  export function useTableState(
    initialState?: any,
    overriddenState?: any,
    options?: {
      reducer?: (oldState: any, newState: any, type: string) => any;
      useState?: [any, Dispatch<SetStateAction<any>>];
    }
  ): any;

  export const actions: any;
}



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source