Drop-in spreadsheet (.xlsx / .xls / .csv) importer modal for React 19 + Bootstrap 5 + Yup.
A focused reimplementation of react-spreadsheet-import:
- React 19 compatible
- Bootstrap 5 (
react-bootstrap) instead of Chakra UI - Yup schema as the validation source of truth
exceljsfor parsingreact-data-gridfor the editable validation stepfuse.jsfor auto-mapping spreadsheet headers to template fields
npm install @icon/react-spreadsheet-importerPeer deps: react, react-dom, react-bootstrap, bootstrap, yup.
import "bootstrap/dist/css/bootstrap.min.css";
import "@icon/react-spreadsheet-importer/styles.css";
import { ReactSpreadsheetImport } from "@icon/react-spreadsheet-importer";
import * as yup from "yup";
const schema = yup.object({
firstName: yup.string().required().max(20),
lastName: yup.string().required().max(20),
email: yup.string().email().required(),
});
const fields = [
{ key: "firstName", label: "First Name", required: true, alternateMatches: ["first"], example: "John" },
{ key: "lastName", label: "Last Name", required: true, alternateMatches: ["last"], example: "Doe" },
{ key: "email", label: "Email", required: true, unique: true, example: "user@company.com" },
] as const;
<ReactSpreadsheetImport
isOpen={open}
onClose={() => setOpen(false)}
fields={fields}
schema={schema}
allowInvalidSubmit={false}
maxRecords={1000}
onSubmit={(result, file) => {
console.log(result.validData, result.invalidData);
}}
/>| Property | Description |
|---|---|
key |
Object key produced for this column. |
label |
Human label shown in the match step and grid header. |
required |
Marks the field as required to advance past column matching. The Yup schema enforces values. |
unique |
Cross-row uniqueness check (Yup can't express this). |
alternateMatches |
Strings considered when fuzzy-matching incoming spreadsheet headers. |
example |
Sample value shown in the upload-step preview. |
Pass a Yup ObjectSchema whose keys match fields[].key. The validator runs per row with abortEarly: false, so all field errors surface at once. Cross-row constraints (unique) are handled by the importer outside Yup. An optional rowHook can mutate values or add extra errors after Yup runs.
uploadStepHook, selectHeaderStepHook, matchColumnsStepHook mirror the original API and let host apps observe / transform data between steps (e.g. to drive an external progress indicator).
- No Chakra
customThemeprop. Theme via Bootstrap CSS variables / SCSS overrides;.rsi-*class hooks are exposed instyles.css. - No per-field
validations: [...]array. Use a Yup schema; useunique: trueon the field for cross-row checks. - Fewer translation keys. Trimmed to the surface this lib actually renders.