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.
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,
useNotificationProvider,
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={useNotificationProvider}
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;
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.
...
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.
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
npm create refine-app@latest -- --example use-simple-list-antd