CSV Import
You can easily import CSV files for any resource by using refine's customizable useImport
hook, optionally with <ImportButton>
component. useImport
hook returns the necessary props for <ImportButton>
component.
Internally, useImport
uses Papa Parse to parse the CSV file contents.
Usage
We'll use the useImport
hook and add the <ImportButton>
with properties returned from useImport
. When the button gets triggered, it creates the imported resources using create
or createMany
dataProvider methods under the hood.
import { List, useImport, ImportButton } from '@refinedev/antd'
export const PostList: React.FC = () => {
const importProps = useImport<IPostFile>()
return (
<List
headerProps={{
extra: <ImportButton {...importProps} />,
}}
>
...
</List>
)
}
interface IPostFile {
id: number
title: string
content: string
userId: number
categoryId: number
status: 'published' | 'draft' | 'rejected'
}
interface IPost {
id: number
title: string
content: string
status: 'published' | 'draft' | 'rejected'
category: { id: number }
user: { id: number }
}
As an example, let's say we have a CSV file like this:
"title","content","status","categoryId","userId"
"dummy title 1","dummy content 1","rejected","3","8"
"dummy title 2","dummy content 2","draft","44","8"
"dummy title 3","cummy content 3","published","41","10"
We need to map the CSV data to the API's data. In our case, we have a categoryId
and userId
in CSV. For the API, we need to send the category
and user
objects. To do this, we'll use the mapData
prop of useImport
hook.
import { List, useImport, ImportButton } from '@refinedev/antd'
export const PostList: React.FC = () => {
const importProps = useImport<IPostFile>({
mapData: (item) => {
return {
title: item.title,
content: item.content,
status: item.status,
category: {
id: item.categoryId,
},
user: {
id: item.userId,
},
}
},
})
return (
<List
headerProps={{
extra: <ImportButton {...importProps} />,
}}
>
...
</List>
)
}
interface IPostFile {
id: number
title: string
content: string
userId: number
categoryId: number
status: 'published' | 'draft' | 'rejected'
}
interface IPost {
id: number
title: string
content: string
status: 'published' | 'draft' | 'rejected'
category: { id: number }
user: { id: number }
}
And it's done. When you click on the button and provide a CSV file of the headers "title"
,"content"
,"status"
,"categoryId"
and "userId"
, it should be mapped and imported. Mapped data is the request payload. Either as part of an array or by itself as part of every request. In our example, it fires POST
request/requests like this:
{
"title": "dummy title 1",
"content": "dummy content 1",
"status": "rejected",
"category": {
"id": "3"
},
"user": {
"id": "8"
}
}
Depending on the batchSize
option, posts can get sent one by one or as batches. By default, all records are sent in one createMany
call.
Example
npm create refine-app@latest -- --example import-export-antd