Skip to main content
Version: 4.xx.xx

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.

import React, { useState } from "react";
import { useImport, useList } from "@refinedev/core";

export const HomePage = () => {
  const { data } = useList({
      resource: "products",
      sorters: [{ field: "id", order: "desc" }],
  });
  const products = data?.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.

products.csv
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 CSV files 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.

import React from "react";
import { useExport, useList } from "@refinedev/core";

export const HomePage = () => {
  const { data } = useList({ resource: "products" });
  const products = data?.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.