useTable
By using useTable, you are able to get properties that are compatible with Ant Design <Table> component. All features such as sorting, filtering and pagination comes as out of box.
Basic usage
Lets say that the data we are going to show on the table came like this from the endpoint:
[
{
"id": 182,
"title": "A aspernatur rerum molestiae.",
"content": "Natus molestias incidunt voluptatibus. Libero delectus facilis...",
"status": "published"
},
{
"id": 989,
"title": "A molestiae vel voluptatem enim.",
"content": "Voluptas consequatur quia beatae. Ipsa est qui culpa deleniti...",
"status": "draft",
"createdAt": "2020-01-28T02:57:58.892Z"
}
]
If we want to make a sorting page where we show the id, title and content values:
import { List, Table, TextField, useTable } from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const { tableProps } = useTable<IPost>();
return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
<Table.Column dataIndex="content" title="Content" />
</Table>
</List>
);
};
interface IPost {
id: number;
title: string;
content: string;
status: "published" | "draft" | "rejected";
}
In a page in resource given to <Refine> component, useTable decides which sources are going to be shown automatically.
If you want to show the data that comes from the endpoint of another resource . You can do so with the resource: string option in the option object that the useTable(options) hook takes.
If the resource option is given, syncWithLocation will not work.
useTable uses useMany while pulling data from the given resource.
Listing
If you want to make a change in the pagination of the <Table>. You should pass the pagination object of the tableProps to the pagination property of the <Table> as below.
const { tableProps } = useTable<IPost>();
<Table
{...tableProps}
rowKey="id"
pagination={{
...tableProps.pagination,
position: ["bottomCenter"],
size: "small",
}}
>
...
</Table>;
To disable pagination, you can set hasPagination property to false which is true by default. If hasPagination has set to false, pagination elements will be hidden in the <Table/>. If you want to handle the pagination on the client-side you can override the pagination property in tableProps.
Sorting
If we want to give a column the sorting property, the corresponding <Table.Column> component must be given the sorter property.
import {
List,
Table,
TextField,
useTable,
getDefaultSortOrder,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const { tableProps, sorter } = useTable<IPost>();
return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
dataIndex="id"
title="ID"
render={(value) => <TextField value={value} />}
sorter
defaultSortOrder={getDefaultSortOrder("id", sorter)}
/>
<Table.Column
dataIndex="title"
title="Title"
render={(value) => <TextField value={value} />}
sorter={{ multiple: 1 }}
defaultSortOrder={getDefaultSortOrder("title", sorter)}
/>
<Table.Column dataIndex="content" title="Content" />
</Table>
</List>
);
};
During the sorting process, the key property of your <Column /> component is used as the property name in the API request. If your Column component does not have a key value, the dataIndex property is used.
It can be used when your DataIndex and your sorting key are different.
When using multiple sorting, multiple value we had given to the sorter property specifies the priority of this column in sorting.

Initial sort status
const { tableProps, sorter } = useTable<IPost>({
initialSorter: [
{
field: "title",
order: "asc",
},
],
});
By using initialSorter setting, you can select which field is going to start with which sorting status ("asc" or "desc").
If you're using the initialSorter, don't forget to add getDefaultSortOrder to your <Table.Column> component. Otherwise, during filter and paging operations, the initialSorter might be lost.
...
<Table.Column
dataIndex="title"
title="Title"
sorter={{ multiple: 2 }}
defaultSortOrder={getDefaultSortOrder("title", sorter)}
/>
...
Filtering
Every post that comes from endpoint has a status value. This value can either be published or draft. We can show the status value with a Ant Design <TagField>:
...
<Table.Column
dataIndex="status"
title="Status"
render={(value) => <TagField value={value} />}
/>
...
We can use the filterDropdown property to make filtering based on the status value. In order to do this, we need to put the filtering form inside the <FilterDropdown> component and pass the properties coming to the function to these component's properties:
import {
List,
Table,
Radio,
FilterDropdown,
TagField,
useTable,
getDefaultSortOrder,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const { tableProps, sorter } = useTable<IPost>({
initialSorter: [
{
field: "title",
order: "asc",
},
],
});
return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" sorter />
<Table.Column
dataIndex="title"
title="Title"
sorter={{ multiple: 2 }}
defaultSortOrder={getDefaultSortOrder("title", sorter)}
/>
<Table.Column
dataIndex="content"
title="Content"
sorter={{ multiple: 1 }}
/>
<Table.Column
dataIndex="status"
title="Status"
render={(value) => <TagField value={value} />}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Radio.Group>
<Radio value="published">Published</Radio>
<Radio value="draft">Draft</Radio>
<Radio value="rejected">Rejected</Radio>
</Radio.Group>
</FilterDropdown>
)}
/>
</Table>
</List>
);
};

Default filter value
In order to set a default filter value, you can use the initialFilter option of the useTable(options) hook.
const { tableProps, sorter, filters } = useTable<IPost>({
initialSorter: [
{
field: "title",
order: "asc",
},
],
initialFilter: [
{
field: "status",
operator: "eq",
value: "draft",
},
],
});
If you give default filter values, defaultFilteredValue property needs to be properly given to the relevant <Table.Column> components so that those filter fields come with default values when the page is opened.
import { getDefaultFilter } from "@pankod/refine-core";
import {
List,
Table,
Radio,
FilterDropdown,
TagField,
useTable,
getDefaultSortOrder,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const { tableProps, sorter, filters } = useTable<IPost>({
initialSorter: [
{
field: "title",
order: "asc",
},
],
initialFilter: [
{
field: "status",
operator: "eq",
value: "draft",
},
],
});
return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" sorter />
<Table.Column
dataIndex="title"
title="Title"
sorter={{ multiple: 2 }}
defaultSortOrder={getDefaultSortOrder("title", sorter)}
/>
<Table.Column
dataIndex="content"
title="Content"
sorter={{ multiple: 1 }}
/>
<Table.Column
dataIndex="status"
title="Status"
render={(value) => <TagField value={value} />}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Radio.Group>
<Radio value="published">Published</Radio>
<Radio value="draft">Draft</Radio>
<Radio value="rejected">Rejected</Radio>
</Radio.Group>
</FilterDropdown>
)}
defaultFilteredValue={getDefaultFilter("status", filters)}
/>
</Table>
</List>
);
};
Filters we give to initialFilter are default filters. In order to prevent filters from being changed, permanentFilter must be used instead of initialFilter.
API
Properties
Type Parameters
| Property | Desription | Type | Default |
|---|---|---|---|
| TData | Result data of the query. Extends BaseRecord | BaseRecord | BaseRecord |
| TError | Custom error object that extends HttpError | HttpError | HttpError |
| TSearchVariables | Values for search params | {} |
Return values
| Property | Description | Type |
|---|---|---|
| searchFormProps | Ant Design <Form> props | FormProps<TSearchVariables> |
| tableProps | Ant Design <Table> props | TableProps<TData> |
| tableQueryResult | Result of the react-query's useQuery | QueryObserverResult<{ data: TData[]; total: number; }, TError> |
| sorter | Current sorting state | CrudSorting |
| filters | Current filters state | CrudFilters |
| setFilters | A function that accepts a new filter state | - (filters: CrudFilters, behavior?: "merge" \| "replace" = "merge") => void - (setter: (previousFilters: CrudFilters) => CrudFilters) => void |
| setSorter | A function that accepts a new sorter state. | (sorter: CrudSorting) => void |