react-csv-autopilot
v1.2.1
Published
React hooks for CSV export with automatic pagination - drop the function, we handle the rest
Maintainers
Readme
react-csv-autopilot
Drop the function, we handle the rest.
A React library for exporting large datasets to CSV with automatic pagination, streaming, and progress tracking. Built with Web Workers for non-blocking performance and File System Access API for efficient file writing.
Features
- Automatic Pagination - Just provide a
getNextPagefunction, we handle the rest - Streaming Export - Uses ReadableStream for memory-efficient large file exports
- Non-blocking - Web Workers for CSV conversion without freezing the UI
- Progress Tracking - Real-time progress updates via BroadcastChannel
- TypeScript - Full type safety with TypeScript definitions
- Zero Dependencies - Only React as peer dependency
- Framework Agnostic Core - Use the core logic in any JavaScript environment
Installation
npm install react-csv-autopilotyarn add react-csv-autopilotpnpm add react-csv-autopilotQuick Start
import { useExportCSV, useMessageExportCSV } from 'react-csv-autopilot';
function ExportButton() {
const { handler } = useExportCSV();
// Track export progress
useMessageExportCSV((progress) => {
if (progress.type === 'progress') {
console.log(`${progress.loadedItemsCount}/${progress.total}`);
}
});
const handleExport = async () => {
await handler.execute({
fileName: 'users-export',
columns: [
{ key: 'id', label: 'ID' },
{ key: 'name', label: 'Full Name' },
{ key: 'email', label: 'Email Address' },
],
getNextPage: async (offset) => {
// Fetch your data - this will be called automatically
const response = await fetch(`/api/users?page=${offset}&limit=100`);
const data = await response.json();
return {
rows: data.users,
total: data.totalCount,
};
},
});
};
return <button onClick={handleExport}>Export to CSV</button>;
}📖 API Reference
useExportCSV()
Hook that provides access to the CSV export controller.
Returns:
{
handler: ExportController // Controller instance for executing exports
}Example:
const { handler } = useExportCSV();
await handler.execute({
fileName: 'data-export',
columns: [...],
getNextPage: async (offset) => {...}
});useMessageExportCSV(callback, channelName?)
Hook for tracking export progress in real-time.
Parameters:
callback: (payload: ExportProgressPayload) => void- Called on each progress updatechannelName?: string- Optional custom channel name (default:'EXPORT_CSV_CHANNEL')
Payload Type:
type ExportProgressPayload = {
total: number;
loadedItemsCount: number;
type: 'progress' | 'done' | 'failed';
};Example:
const [progress, setProgress] = useState({ loaded: 0, total: 0 });
useMessageExportCSV((payload) => {
setProgress({
loaded: payload.loadedItemsCount,
total: payload.total,
});
if (payload.type === 'done') {
console.log('Export completed!');
}
});Types
ExportParams
type ExportParams = {
fileName: string;
columns: Column[];
getNextPage: (offset: number) => Promise<{ rows: any[]; total: number }>;
};Column
type Column = {
key: string;
label: string;
timezone?: 'UTC' | string;
formatType?: 'dateFull' | 'dateMediumTime' | 'timeShort' | 'numDecimal' | 'numCompact' | 'numCurrency' | 'numPercent';
};Pagination Strategies
API with page numbers:
getNextPage: async (offset) => {
const page = offset + 1; // Convert to 1-based pagination
const response = await fetch(`/api/data?page=${page}&size=100`);
return await response.json();
}API with cursor-based pagination:
let nextCursor = null;
getNextPage: async (offset) => {
const url = offset === 0
? '/api/data?limit=100'
: `/api/data?cursor=${nextCursor}&limit=100`;
const response = await fetch(url);
const data = await response.json();
nextCursor = data.nextCursor;
return {
rows: data.items,
total: data.totalCount,
};
}Architecture
How It Works
- Stream-based Export - Uses
ReadableStreamand File System Access API for efficient file writing - Web Workers - CSV conversion happens in a separate thread to keep UI responsive
- Automatic Pagination - Calls your
getNextPagefunction repeatedly until all data is fetched - Progress Tracking - Uses
BroadcastChannelto communicate progress across components
┌─────────────────┐
│ React Hook │
│ useExportCSV() │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────┐
│ Export │─────▶│ Web Worker │
│ Controller │ │ (CSV Convert)│
└────────┬────────┘ └──────────────┘
│
▼
┌─────────────────┐ ┌──────────────┐
│ ReadableStream │─────▶│ File System │
│ (Pagination) │ │ Access API │
└─────────────────┘ └──────────────┘Browser Compatibility
Requires browsers with support for:
- File System Access API (Chrome 86+, Edge 86+)
- Web Workers (All modern browsers)
- ReadableStream (All modern browsers)
Note: For browsers without File System Access API, the library will fall back to Blob-based download.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © Pavlo Kuzina
🔗 Links
- npm Package: react-csv-autopilot
- Repository: GitHub - utils-kit
- Issues: GitHub Issues
- Monorepo: Part of utils-kit collection
Related Packages
- react-url-query-params - Type-safe URL query parameter management
