Getting Started
React / Vite
Complete setup guide for ImportCSV in React apps (Vite, CRA, etc.)
Installation
npm install @importcsv/react zod
# Optional: for Excel support
npm install xlsxQuick Start (Vite)
import { CSVImporter } from '@importcsv/react';
import { z } from 'zod';
import { useState } from 'react';
// Define your data schema
const userSchema = z.object({
name: z.string().min(1, 'Name is required'),
email: z.string().email('Invalid email address'),
age: z.number().min(18, 'Must be 18 or older').optional(),
role: z.enum(['admin', 'user', 'guest'])
});
type User = z.infer<typeof userSchema>;
function App() {
const [isOpen, setIsOpen] = useState(false);
const [users, setUsers] = useState<User[]>([]);
return (
<div className="App">
<button onClick={() => setIsOpen(true)}>
Import Users
</button>
<CSVImporter
modalIsOpen={isOpen}
modalOnCloseTriggered={() => setIsOpen(false)}
schema={userSchema}
onComplete={(data: User[]) => {
setUsers(data);
setIsOpen(false);
}}
/>
{/* Display imported users */}
{users.length > 0 && (
<div>
<h2>Imported Users ({users.length})</h2>
<ul>
{users.map((user, i) => (
<li key={i}>{user.name} - {user.email}</li>
))}
</ul>
</div>
)}
</div>
);
}
export default App;Inline Mode
Display the importer directly in the page:
import { CSVImporter } from '@importcsv/react';
import { z } from 'zod';
const productSchema = z.object({
name: z.string().min(1),
price: z.number().positive(),
sku: z.string(),
category: z.string()
});
export function ImportPage() {
return (
<div className="container">
<h1>Import Products</h1>
<CSVImporter
isModal={false}
schema={productSchema}
onComplete={(data) => {
console.log('Imported products:', data);
// Send to API, update state, etc.
}}
/>
</div>
);
}API Integration
Process imported data with a backend API:
import { CSVImporter } from '@importcsv/react';
import { z } from 'zod';
import { useState } from 'react';
const contactSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
company: z.string()
});
function App() {
const [isOpen, setIsOpen] = useState(false);
const [loading, setLoading] = useState(false);
const handleComplete = async (data: z.infer<typeof contactSchema>[]) => {
setLoading(true);
try {
const response = await fetch('/api/contacts/import', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ contacts: data })
});
if (response.ok) {
alert(`Successfully imported ${data.length} contacts`);
} else {
alert('Import failed');
}
} catch (error) {
console.error('Import error:', error);
alert('Import failed');
} finally {
setLoading(false);
setIsOpen(false);
}
};
return (
<div className="App">
<button onClick={() => setIsOpen(true)} disabled={loading}>
{loading ? 'Importing...' : 'Import Contacts'}
</button>
<CSVImporter
modalIsOpen={isOpen}
modalOnCloseTriggered={() => setIsOpen(false)}
schema={contactSchema}
onComplete={handleComplete}
/>
</div>
);
}
export default App;Theming
Customize the importer to match your brand:
<CSVImporter
schema={schema}
onComplete={handleComplete}
theme="dark"
primaryColor="#10b981"
/>Available themes:
"default"- Clean, modern light theme"dark"- Dark mode"professional"- Enterprise styling- Custom CSS variables (see Theming Guide)
Create React App (CRA)
ImportCSV works out of the box with CRA. No additional configuration needed:
import { CSVImporter } from '@importcsv/react';
import { z } from 'zod';
import { useState } from 'react';
const schema = z.object({
name: z.string().min(1),
email: z.string().email()
});
type Data = z.infer<typeof schema>;
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="App">
<button onClick={() => setIsOpen(true)}>
Import CSV
</button>
<CSVImporter
modalIsOpen={isOpen}
modalOnCloseTriggered={() => setIsOpen(false)}
schema={schema}
onComplete={(data: Data[]) => {
console.log(data);
setIsOpen(false);
}}
/>
</div>
);
}
export default App;TypeScript
ImportCSV is fully typed. Enable strict type checking:
import { CSVImporter, CSVImporterProps } from '@importcsv/react';
import { z } from 'zod';
const schema = z.object({
name: z.string(),
email: z.string().email()
});
type Contact = z.infer<typeof schema>;
const importerProps: CSVImporterProps = {
schema,
onComplete: (data: Contact[]) => {
// data is fully typed
console.log(data);
}
};
export function ContactImporter() {
return <CSVImporter {...importerProps} />;
}Next Steps
🎨 Headless Components
Build custom UI with primitives
🛡️ Zod Schemas
Advanced validation patterns
📖 API Reference
Complete props documentation
💡 Examples
More advanced examples
Common Issues
Excel files not working
Install the xlsx library:
npm install xlsxBundle size concerns
ImportCSV is ~100KB gzipped. For further optimization, use code splitting:
import { lazy, Suspense } from 'react';
const CSVImporter = lazy(() =>
import('@importcsv/react').then(mod => ({ default: mod.CSVImporter }))
);
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<CSVImporter {...props} />
</Suspense>
);
}Styling conflicts
ImportCSV auto-injects CSS. If you experience conflicts, use the className prop to scope styles:
<CSVImporter
className="my-custom-importer"
{...props}
/>