Skip to main content
🧙‍♂️ refine grants your wishes! Please give us a ⭐️ on GitHub to keep the magic going.
Version: 4.xx.xx

List Search

We will examine how to make an extensive search and filtering with the useSimpleList hook that works with the Ant Design's <List> component.

To do this, let's list posts using the posts resource.

pages/posts/list.tsx
import { useMany } from "@refinedev/core";
import {
List,
useSimpleList,
NumberField,
} from "@refinedev/antd";
import { List as AntdList, Typography, Space } from "antd";

const { Text } = Typography;

export const PostList: React.FC = () => {
const { listProps } = useSimpleList<IPost>();

const categoryIds =
listProps?.dataSource?.map((item) => item.category.id) ?? [];
const { data } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

const renderItem = (item: IPost) => {
const { title, hit, content } = item;

const categoryTitle = data?.data.find(
(category: ICategory) => category.id === item.category.id,
)?.title;

return (
<AntdList.Item
actions={[
<Space key={item.id} direction="vertical" align="end">
<NumberField
value={hit}
options={{
notation: "compact",
}}
/>
<Text>{categoryTitle}</Text>
</Space>,
]}
>
<AntdList.Item.Meta title={title} description={content} />
</AntdList.Item>
);
};

return (
<List>
<AntdList {...listProps} renderItem={renderItem} />
</List>
);
};

interface ICategory {
id: number;
title: string;
}

interface IPost {
id: number;
title: string;
content: string;
hit: number;
category: { id: number };
}

After creating the <PostList> component, add it to the resource with list prop:

import { Refine } from "@refinedev/core";
import {
ThemedLayoutV2,
notificationProvider,
ErrorComponent,
RefineThemes,
} from "@refinedev/antd";
import routerProvider, { NavigateToResource } from "@refinedev/react-router-v6";
import dataProvider from "@refinedev/simple-rest";

import { BrowserRouter, Routes, Route, Outlet } from "react-router-dom";

import { ConfigProvider } from "antd";
import "@refinedev/antd/dist/reset.css";

import { PostList } from "pages/posts";

const API_URL = "https://api.fake-rest.refine.dev";

const App: React.FC = () => {
return (
<BrowserRouter>
<ConfigProvider theme={RefineThemes.Blue}>
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider(API_URL)}
notificationProvider={notificationProvider}
resources={[
{
name: "posts",
list: "/posts",
},
]}
>
<Routes>
<Route index element={<NavigateToResource />} />
<Route
element={
<ThemedLayoutV2>
<Outlet />
</ThemedLayoutV2>
}
>
<Route path="/posts" element={<PostList />} />
</Route>
<Route path="*" element={<ErrorComponent />} />
</Routes>
</Refine>
</ConfigProvider>
</BrowserRouter>
);
};

export default App;
basic list

We will create a form by extracting searchFormProps from useSimpleList. We will use this form for search/filtering. We will also create an interface to determine the types of values from the form.

pages/posts/list.tsx
...

import {
...
CrudFilters,
} from "@refinedev/core";

export const PostList: React.FC = () => {
const { listProps, searchFormProps } = useSimpleList<
IPost,
IPostFilterVariables
>({
onSearch: (params) => {
const filters: CrudFilters = [];
const { category, createdAt } = params;

filters.push(
{
field: "category.id",
operator: "eq",
value: category,
},
{
field: "createdAt",
operator: "gte",
value: createdAt ? createdAt[0].toISOString() : undefined,
},
{
field: "createdAt",
operator: "lte",
value: createdAt ? createdAt[1].toISOString() : undefined,
},
);

return filters;
},
});

// ...

const { selectProps: categorySelectProps } = useSelect<ICategory>({
resource: "categories",
});

return (
<List>
<Form
{...searchFormProps}
layout="vertical"
onValuesChange={() => searchFormProps.form?.submit()}
>
<Space wrap>
<Form.Item label="Category" name="category">
<Select
{...categorySelectProps}
allowClear
placeholder="Search Categories"
/>
</Form.Item>
<Form.Item label="Created At" name="createdAt">
<RangePicker />
</Form.Item>
</Space>
</Form>
<AntdList {...listProps} renderItem={renderItem} />
</List>
);
};

interface IPostFilterVariables {
category: string;
createdAt: [Dayjs, Dayjs];
}

When the form is submitted, the onSearch method runs and we get the search form values. Then the listProps is refreshed according to the criteria.

form list
CAUTION

CrudFilters type object has field, operator, and value properties. These properties help us to filter in which field, with which operator, and with which data.

Example

Run on your local
npm create refine-app@latest -- --example use-simple-list-antd