A powerful, production-ready React CSV import component with intelligent column mapping, real-time validation, and a beautiful, themeable UI.
Seamlessly handle large CSV files with web worker-based parsing and built-in pagination
Quick import workflow for smaller CSV files (no pagination needed)
- Web Worker Processing - Handle large files (100k+ rows) without blocking the UI
- Streaming Parser - Memory-efficient chunk-based parsing
- Real-time Progress - Live progress updates with row count and percentage
- Cancellable Operations - Abort long-running imports at any time
- 18 Built-in Themes - Choose from blue, indigo, purple, pink, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, slate, gray, zinc, neutral, stone
- Custom Themes - Pass any hex color for instant theming
- Custom Trigger - Use your own button or component to trigger the mapper
- Smart Auto-mapping - Automatically matches CSV columns to your fields
- Flexible Field Selection - Define default fields and let users add more
- Inline Editing - Edit cell values directly in the validation step
- Row Management - Add or remove rows before import
- Duplicate Detection - Automatically identifies duplicate rows
- Export Options - Export validated data as JSON or CSV
- Real-time Validation - Instant feedback as users map and edit data
- Custom Validators - Define your own validation rules per field
- Required Fields - Mark fields as required with visual indicators
- Error Filtering - Toggle between all rows and error rows only
- Validation Summary - Clear overview of errors and warnings
- React Component - Drop-in
<CsvMapper />component - React Hook -
useCsvMapper()hook for custom implementations - TypeScript Support - Full type definitions included
- Zero Configuration - Works out of the box with sensible defaults
npm install react-csv-mapperimport { CsvMapper } from 'react-csv-mapper';
function App() {
return (
<CsvMapper
columns={[
{ key: 'name', label: 'Full Name', required: true, default: true },
{ key: 'email', label: 'Email', required: true, default: true },
{ key: 'phone', label: 'Phone Number' }
]}
onSubmit={(data) => {
console.log('Imported data:', data);
}}
theme="indigo" // Optional: Choose from 18 themes or use hex color
/>
);
}<CsvMapper
columns={[...]}
onSubmit={(data) => console.log(data)}
theme="emerald" // Named theme
// OR
theme="#0066ff" // Custom hex color
/><CsvMapper
columns={[...]}
onSubmit={(data) => console.log(data)}
theme="blue"
trigger={
<button className="my-custom-button">
📊 Import CSV
</button>
}
/>The component supports 18 built-in color themes with TypeScript autocomplete:
type ThemeColor =
| 'blue' | 'indigo' | 'purple' | 'pink'
| 'red' | 'orange' | 'amber' | 'yellow'
| 'lime' | 'green' | 'emerald' | 'teal'
| 'cyan' | 'sky' | 'slate' | 'gray'
| 'zinc' | 'neutral' | 'stone';
<CsvMapper theme="indigo" ... />Or use any custom hex color:
<CsvMapper theme="#7c3aed" ... />The theme automatically applies to:
- Primary buttons (Next, Submit)
- Links and interactive text
- Selected header rows
- Radio buttons and checkboxes
- Progress bars
- Borders on focus
- Active pagination buttons
| Prop | Type | Required | Description |
|---|---|---|---|
columns |
CsvColumn[] |
✅ Yes | Array of column definitions |
onSubmit |
(data: Record<string, string>[]) => void |
✅ Yes | Callback when data is submitted |
theme |
ThemeColor | string |
❌ No | Theme color (named or hex) |
trigger |
React.ReactElement |
❌ No | Custom trigger button |
container |
string |
❌ No | Container selector (default: 'body') |
interface CsvColumn {
key: string; // Unique identifier
label: string; // Display label
required?: boolean; // Is required?
default?: boolean; // Is selected by default?
validate?: (value: string) => true | string; // Custom validation
}import { useCsvMapper } from 'react-csv-mapper';
const { init, destroy } = useCsvMapper({
columns: [...],
onSubmit: (data) => console.log(data)
});
// Open mapper
<button onClick={init}>Import CSV</button><CsvMapper
columns={[
{
key: 'email',
label: 'Email Address',
required: true,
validate: (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(value) ? true : 'Invalid email format';
}
},
{
key: 'age',
label: 'Age',
validate: (value) => {
if (!value) return true;
const age = parseInt(value);
return (age >= 0 && age <= 120) ? true : 'Age must be 0-120';
}
}
]}
onSubmit={async (data) => {
await fetch('/api/import', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
}}
theme="purple"
/>// Define all possible fields
const allFields = [
{ key: 'firstName', label: 'First Name', default: true },
{ key: 'lastName', label: 'Last Name', default: true },
{ key: 'email', label: 'Email', required: true, default: true },
{ key: 'phone', label: 'Phone' },
{ key: 'company', label: 'Company' },
{ key: 'title', label: 'Job Title' },
{ key: 'address', label: 'Address' },
{ key: 'city', label: 'City' },
{ key: 'country', label: 'Country' }
];
// Users can select which fields to import
<CsvMapper
columns={allFields}
onSubmit={(data) => console.log(data)}
theme="teal"
/>import { CsvMapper, CsvColumn, ThemeColor } from 'react-csv-mapper';
interface UserData {
name: string;
email: string;
phone: string;
}
const columns: CsvColumn[] = [
{ key: 'name', label: 'Full Name', required: true, default: true },
{ key: 'email', label: 'Email', required: true, default: true },
{ key: 'phone', label: 'Phone Number' }
];
const theme: ThemeColor = 'indigo';
function ImportUsers() {
const handleSubmit = (data: Record<string, string>[]) => {
const users: UserData[] = data.map(row => ({
name: row.name,
email: row.email,
phone: row.phone || ''
}));
console.log(users);
};
return <CsvMapper columns={columns} onSubmit={handleSubmit} theme={theme} />;
}- Upload - Drag & drop or paste CSV data
- Select Header - Choose which row contains column headers (with pagination for large files)
- Map Columns - Auto-mapped or manually map CSV columns to your fields
- Validate & Edit - Review data, fix errors, add/remove rows (paginated view)
- Submit - Clean, validated data ready for your API
- ✅ Chrome (latest)
- ✅ Firefox (latest)
- ✅ Safari (latest)
- ✅ Edge (latest)
Requires Web Worker support for large file processing.
MIT © Ahmad Nadeem
Contributions, issues and feature requests are welcome!
Give a ⭐️ if this project helped you!

