CSV Import - Export
Importing and exporting data are essential tasks for managing information in data extensive applications. With CSV export and import, we can speed up the process of data entry and data migration.
Refine provides useImport and useExport hooks for both bulk importing and exporting data, making it easy to move large datasets between your application and external sources.
Import
useImport hook allows you to import data from a CSV file. For each row in the file, it calls the create or createMany method of your data provider according to your configuration.
Internally, it uses Papa Parse to parse the file contents.
Code Example
// file: /App.tsx
import React from "react";
import { Refine } from "@refinedev/core";
import dataProvider from "@refinedev/simple-rest";
import { HomePage } from "./home-page";
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
resources={[
{
name: "products",
},
]}
>
<HomePage />
</Refine>
);
};
export default App;// file: /home-page.tsx
import React, { useState } from "react";
import { useImport, useList } from "@refinedev/core";
export const HomePage = () => {
const { result } = useList({
resource: "products",
sorters: [{ field: "id", order: "desc" }],
});
const products = result?.data;
const [importProgress, setImportProgress] = useState({
processed: 0,
total: 0,
});
const { inputProps, isLoading } = useImport<IProduct>({
resource: "products",
onFinish: () => {
alert("Import completed!");
},
onProgress: (progress) => {
setImportProgress({
processed: progress.processedAmount,
total: progress.totalAmount,
});
},
});
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
padding: "16px",
}}
>
<div style={{ display: "flex", alignItems: "center", gap: "16px" }}>
<h2>Products</h2>
<label
style={{
display: "flex",
alignItems: "center",
gap: "8px",
cursor: "pointer",
padding: "8px",
border: "1px solid #ccc",
borderRadius: "4px",
}}
>
{isLoading ? (
<p>
{importProgress.processed} / {importProgress.total}
</p>
) : (
<p>Import CSV</p>
)}
<input name="csv" {...inputProps} />
</label>
</div>
{products?.map((product) => (
<div key={product.id}>
<h4>
[ID: {product.id}] - {product.name}
</h4>
<p>{product.description}</p>
</div>
))}
</div>
);
};
interface IProduct {
id: string;
name: string;
description: string;
material: string;
price: number;
category: {
id: string;
};
}You can use the following CSV file to test the import feature.
name,material,description,price,category
"Test Product 1","Test Material 1","Test Description 1","100","{""id"":1}"
"Test Product 2","Test Material 2","Test Description 2","200","{""id"":2}"
"Test Product 3","Test Material 3","Test Description 3","300","{""id"":3}"
Refine also provides <ImportButton />. It's compatible with useImport hook to easily handle the import process.
Export
useExport hook allows you to export data as a CSV file. It calls the getList method of your data provider and downloads the data as a CSV file.
Internally, it uses Papa Parse to create the CSV file.
🚨 The download feature for
CSVfiles does not function within an iframe (live-previews). You can copy the code and run it in your own project to see it in action.
Code Example
// file: /App.tsx
import React from "react";
import { Refine } from "@refinedev/core";
import dataProvider from "@refinedev/simple-rest";
import { HomePage } from "./home-page";
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
resources={[
{
name: "products",
},
]}
>
<HomePage />
</Refine>
);
};
export default App;// file: /home-page.tsx
import React from "react";
import { useExport, useList } from "@refinedev/core";
export const HomePage = () => {
const { result } = useList({ resource: "products" });
const products = result?.data;
const { triggerExport, isLoading } = useExport<IProduct>({
resource: "products",
mapData: (item) => {
return {
...item,
// category is an object, we need to stringify it
category: JSON.stringify(item.category),
};
},
});
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
padding: "16px",
}}
>
<div style={{ display: "flex", alignItems: "center", gap: "16px" }}>
<h2>Products</h2>
<button onClick={triggerExport} disabled={isLoading}>
{isLoading ? "Exporting..." : "Export Products"}
</button>
</div>
{products?.map((product) => (
<div key={product.id}>
<h4>[ID: {product.id}] - {product.name}</h4>
<p>{product.description}</p>
</div>
))}
</div>
);
};
interface IProduct {
id: string;
name: string;
description: string;
material: string;
price: number;
category: {
id: string;
};
}Refine also provides <ExportButton />. It's compatible with useExport hook to easily handle the export process.
