# Server-side Filtering

> Learn how to integrate server-side filtering with your InfiniteTable React DataGrid

Canonical page: https://infinite-table.com/docs/learn/filtering/filtering-server-side

If you're using a remote [`data`](https://infinite-table.com/docs/reference/datasource-props/index.md#data) prop (a function that returns a `Promise`) on the `<DataSource />` component, the filtering will happen server-side by default.

You can explicitly configure server-side filtering by using [filterMode="remote"](https://infinite-table.com/docs/reference/datasource-props/index.md#filterMode).

When remote filtering is enabled, the [`data`](https://infinite-table.com/docs/reference/datasource-props/index.md#data) function prop will be called with an object argument that includes the `filterValue` property, so the filters can be sent to the server for performing the correct filtering operations.

Obviously the filtering can be combined with sorting, grouping, etc.

It's up to the [`data`](https://infinite-table.com/docs/reference/datasource-props/index.md#data) function prop to send the correct parameters to the server for remote operations.

The returned JSON can include both

- a `totalCount` property (`number`) and
- a `totalCountUnfiltered` property (also `number`) - to inform the `<DataSource />` of the size of the data, both with and without the applied filters.

**Example: Server-side filtering example**

All the filtering in this example happens server-side.

This example also does server-side (multiple) sorting.

```ts
import * as React from 'react';

import {
  DataSourceData,
  InfiniteTable,
  InfiniteTablePropColumns,
  DataSource,
  DataSourcePropSortInfo,
  DataSourcePropFilterValue,
} from '@infinite-table/infinite-react';

type Developer = {
  id: number;
  firstName: string;
  lastName: string;

  currency: string;
  preferredLanguage: string;
  stack: string;
  canDesign: 'yes' | 'no';

  salary: number;
};

const data: DataSourceData<Developer> = ({ filterValue, sortInfo }) => {
  if (sortInfo && !Array.isArray(sortInfo)) {
    sortInfo = [sortInfo];
  }
  const args = [
    sortInfo
      ? 'sortInfo=' +
        JSON.stringify(
          sortInfo.map((s) => ({
            field: s.field,
            dir: s.dir,
          })),
        )
      : null,

    filterValue
      ? 'filterBy=' +
        JSON.stringify(
          filterValue.map(({ field, filter }) => {
            return {
              field: field,
              operator: filter.operator,
              value:
                filter.type === 'number' ? Number(filter.value) : filter.value,
            };
          }),
        )
      : null,
  ]
    .filter(Boolean)
    .join('&');

  return fetch(process.env.NEXT_PUBLIC_BASE_URL + `/developers1k-sql?` + args)
    .then((r) => r.json())
    .then((data: Developer[]) => data);
};

const columns: InfiniteTablePropColumns<Developer> = {
  id: {
    field: 'id',
    type: 'number',
    defaultWidth: 100,
  },
  salary: {
    field: 'salary',
    type: 'number',
  },

  firstName: {
    field: 'firstName',
  },
  stack: { field: 'stack' },
  currency: { field: 'currency' },
};

const domProps = {
  style: {
    height: '100%',
  },
};
const defaultSortInfo: DataSourcePropSortInfo<Developer> = [
  {
    field: 'stack',
    dir: 1,
  },
  {
    field: 'salary',
    dir: 1,
  },
];

const defaultFilterValue: DataSourcePropFilterValue<Developer> = [];

const shouldReloadData = {
  sortInfo: true,
};

export default () => {
  return (
    <>
      <React.StrictMode>
        <DataSource<Developer>
          data={data}
          primaryKey="id"
          defaultFilterValue={defaultFilterValue}
          defaultSortInfo={defaultSortInfo}
          shouldReloadData={shouldReloadData}
        >
          <InfiniteTable<Developer>
            debugId="server-side-example"
            domProps={domProps}
            columnDefaultWidth={150}
            columnMinWidth={50}
            columns={columns}
          />
        </DataSource>
      </React.StrictMode>
    </>
  );
};
```

When the filter value for a column matches the empty value - as specified in the [filterTypes.operator.emptyValues](https://infinite-table.com/docs/reference/datasource-props/index.md#filterTypes) - that value is not sent to the server as part of the `filterValue` array.

When doing server-side filtering, it's your responsability as a developer to make sure you're sending the correct filtering parameters to the server, in a way the server understands it.

This means that the filter values, the filter type and the names of the operators are known to the server and there is a clear convention of what is supported or not.

## Batch filtering

In order to reduce the number of requests sent to the server, filtering will be batched by default.

Batching is controlled by the [`filterDelay`](https://infinite-table.com/docs/reference/datasource-props/index.md#filterDelay) prop, which, if not specified, defaults to `200` milliseconds. This means, any changes to the column filters, that happen inside a 200ms window (or the current value of [`filterDelay`](https://infinite-table.com/docs/reference/datasource-props/index.md#filterDelay)), will be debounced and only the last value will be sent to the server.

If you want to prevent debouncing/batching filter values, you can set [`filterDelay`](https://infinite-table.com/docs/reference/datasource-props/index.md#filterDelay) to `0`.
