react-spreadsheet-import

repository·master·Indexed 19 days ago

https://github.com/ugnissoftware/react-spreadsheet-import

A React component for importing XLS, XLSX, and CSV files using Chakra UI. It provides a complete workflow including file uploading, parsing, column mapping, data validation, and editing. Version 4.7.1 features automatic header mapping, custom validation rules (required, unique, regex), and flexible lifecycle hooks to transform data during the import process.

Tokens
7.2K
Snippets
22
Records
27
Agent score
67%

What's inside react-spreadsheet-import

  1. Transform and validate data with Hooks

    master

    You can use hooks to alter raw data or perform custom validations at different stages of the import flow:

    Step-based Hooks (Run once per step)

    • uploadStepHook: Runs once after the file is uploaded.
    • selectHeaderStepHook: Runs once after the header row is selected.
    • matchColumnsStepHook: Runs once after column mapping. Best for expensive operations.

    Validation Step Hooks

    • tableHook: Runs at the start and on any change. Runs on all rows. Use this for complex validations where rows depend on each other (expensive).
    • rowHook: Runs at the start and on any row change. Runs only on changed rows. Best for most transformations and validations (fast).
    <ReactSpreadsheetImport
      rowHook={(data, addError) => {
        // Validation
        if (data.name === "John") {
          addError("name", { message: "No Johns allowed", level: "info" })
        }
        // Transformation
        return { ...data, name: "Not John" }
      }}
    />
  2. Customize component styles via customTheme

    master

    The component uses Chakra UI. You can override styles using the customTheme prop in three ways:

    1. Global Colors: Override the colors object, including the rsi brand color scale.
    2. Component Types: Override all components of a specific type (e.g., all Button components) using components.
    3. Step-specific Components: Target components within a specific step (e.g., UploadStep).
    // Example: Changing global brand colors
    <ReactSpreadsheetImport
        isOpen={isOpen}
        onClose={onClose}
        onSubmit={setData}
        customTheme={{
          colors: {
            background: 'white',
            rsi: {
              500: 'teal',
            },
          },
        }}
      />
  3. Understand the Result<T> data format

    master

    When the onSubmit callback is triggered, it receives a Result<T> object. This object categorizes the imported rows based on their validation status.

    Result Structure

    • validData: An array of Data<T> objects that passed all validations.
    • invalidData: An array of Data<T> objects that failed validation.
    • all: An array containing all rows, where each row is augmented with Meta (information about validation errors and status).

    Data<T> is a record where keys are the field keys defined in your Fields<T> configuration, and values are string | boolean | undefined.

  4. Basic usage of ReactSpreadsheetImport

    master

    To use the component, import ReactSpreadsheetImport and provide the required props: isOpen (boolean), onClose (callback), onSubmit (callback providing the data array and file), and fields (array defining the data structure).

    import { ReactSpreadsheetImport } from "react-spreadsheet-import";
    
    <ReactSpreadsheetImport 
      isOpen={isOpen} 
      onClose={onClose} 
      onSubmit={onSubmit} 
      fields={fields} 
    />
  5. Define data fields and validation rules

    master

    The fields prop is an array of objects that describes the data you want to collect. Each field object can include:

    • label: The display name in the table header.
    • key: The key used in the final data object passed to onSubmit.
    • alternateMatches: (Optional) Array of strings to improve automatic column matching.
    • fieldType: An object with type (either "input", "checkbox", or "select").
    • example: (Optional) A string showing expected data format.
    • validations: An array of validation objects with rule ("required", "unique", or "regex"), errorMessage, and level ("info", "warning", or "error", defaulting to "error").
    const fields = [
      {
        label: "Name",
        key: "name",
        alternateMatches: ["first name", "first"],
        fieldType: {
          type: "input",
        },
        example: "Stephanie",
        validations: [
          {
            rule: "required",
            errorMessage: "Name is required",
            level: "error",
          },
        ],
      },
    ] as const
  6. Skip to a specific step using initialStepState

    master

    You can start the import flow from a specific step by providing the initialStepState prop. The state type depends on the step:

    • StepType.upload: No extra data needed.
    • StepType.selectSheet: Requires workbook (XLSX.WorkBook).
    • StepType.selectHeader: Requires data (Array of RawData).
    • StepType.matchColumns: Requires data (Array of RawData) and headerValues (Array of strings).
    • StepType.validateData: Requires data (any array).
    import { ReactSpreadsheetImport, StepType } from "react-spreadsheet-import";
    
    <ReactSpreadsheetImport
      initialStepState={{
        type: StepType.matchColumns,
        data: [
          ["Josh", "2"],
          ["Charlie", "3"],
          ["Lena", "50"],
        ],
        headerValues: ["name", "age"],
      }}
    />
  7. Configure default props for ReactSpreadsheetImport

    master

    The component uses a set of default properties that control the behavior of the import flow. You can override these by passing your own configuration via the RsiProps object.

    Key default behaviors include:

    • autoMapHeaders: true: Automatically attempts to map spreadsheet headers to your data keys.
    • autoMapSelectValues: false: Does not automatically map select values.
    • allowInvalidSubmit: true: Allows the user to proceed even if there are validation errors.
    • autoMapDistance: 2: The threshold for automatic header mapping.
    • isNavigationEnabled: false: Disables step-by-step navigation by default.
    • dateFormat: "yyyy-mm-dd": The default date format used for parsing.
    • parseRaw: true: Enables raw parsing of data.
    export const defaultRSIProps: Partial<RsiProps<any>> = {
      autoMapHeaders: true,
      autoMapSelectValues: false,
      allowInvalidSubmit: true,
      autoMapDistance: 2,
      isNavigationEnabled: false,
      translations: translations,
      uploadStepHook: async (value) => value,
      selectHeaderStepHook: async (headerValues, data) => ({ headerValues, data }),
      matchColumnsStepHook: async (table) => table,
      dateFormat: "yyyy-mm-dd",
      parseRaw: true,
    } as const
  8. Reference: Optional Props

    master

    A list of available optional configuration props for ReactSpreadsheetImport.

    allowInvalidSubmit?: boolean (Default: true)
    translations?: object
    customTheme?: object
    maxRecords?: number
    maxFileSize?: number (in bytes)
    autoMapHeaders?: boolean (Default: true)
    autoMapSelectValues?: boolean (Default: false)
    autoMapDistance?: number (Default: 2)
    isNavigationEnabled?: boolean (Default: false)
  9. Customize the import flow with step hooks

    master

    You can intercept and transform data at different stages of the import process using step hooks. These hooks are part of the defaultRSIProps and can be overridden in your component configuration:

    • uploadStepHook: An async function that receives the uploaded value. Use this to transform the file or data immediately after upload.
    • selectHeaderStepHook: An async function that receives headerValues and data. It expects a return object of type { headerValues, data } to allow modification of headers or the dataset during the header selection step.
    • matchColumnsStepHook: An async function that receives the table object. Use this to transform the table structure during the column matching step.
    const props = {
      uploadStepHook: async (value) => {
        // transform uploaded value
        return value;
      },
      selectHeaderStepHook: async (headerValues, data) => {
        // transform headers or data
        return { headerValues, data };
      },
      matchColumnsStepHook: async (table) => {
        // transform the table
        return table;
      },
    };