CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-dropzone

Simple HTML5 drag-drop zone with React.js

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

React Dropzone

React Dropzone is a React library that provides simple HTML5-compliant drag-and-drop zones for file uploads. It offers a powerful useDropzone hook and convenient Dropzone component wrapper with extensive customization options, file validation, and comprehensive event handling.

Package Information

  • Package Name: react-dropzone
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install react-dropzone or yarn add react-dropzone

Core Imports

import Dropzone, { useDropzone, ErrorCode, FileWithPath } from "react-dropzone";

For CommonJS:

const Dropzone = require("react-dropzone").default;
const { useDropzone, ErrorCode, FileWithPath } = require("react-dropzone");

Basic Usage

import React, { useCallback } from "react";
import { useDropzone } from "react-dropzone";

function MyDropzone() {
  const onDrop = useCallback((acceptedFiles: File[]) => {
    // Process the dropped files
    console.log(acceptedFiles);
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  return (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      {isDragActive ? (
        <p>Drop the files here...</p>
      ) : (
        <p>Drag 'n' drop files here, or click to select files</p>
      )}
    </div>
  );
}

Architecture

React Dropzone is built around modern React patterns:

  • Hook-based API: Primary interface through useDropzone hook (React 16.8+)
  • Component Wrapper: Optional Dropzone component for render prop pattern
  • Event-driven Architecture: Comprehensive drag and drop event handling
  • File Validation System: Built-in validation for file types, sizes, and custom rules
  • Zero Dependencies: Core functionality has no external dependencies beyond React
  • TypeScript Support: Complete type definitions included

Capabilities

useDropzone Hook

The primary interface for creating drag-and-drop zones with full customization options.

/**
 * Creates a drag 'n' drop area with comprehensive configuration options
 * @param options - Configuration options for the dropzone
 * @returns State object with drag states, file arrays, and prop getter functions
 */
function useDropzone(options?: DropzoneOptions): DropzoneState;

interface DropzoneOptions {
  /** Accepted file types as MIME type object (default: undefined - all files) */
  accept?: Accept;
  /** Allow multiple file selection (default: true) */
  multiple?: boolean;
  /** Prevent drops on document (default: true) */
  preventDropOnDocument?: boolean;
  /** Disable click to open file dialog (default: false) */
  noClick?: boolean;
  /** Disable keyboard file dialog triggers (default: false) */
  noKeyboard?: boolean;
  /** Disable drag and drop (default: false) */
  noDrag?: boolean;
  /** Stop drag event bubbling (default: false) */
  noDragEventsBubbling?: boolean;
  /** Minimum file size in bytes (default: 0) */
  minSize?: number;
  /** Maximum file size in bytes (default: Infinity) */
  maxSize?: number;
  /** Maximum number of files (default: 0 - unlimited) */
  maxFiles?: number;
  /** Disable the dropzone (default: false) */
  disabled?: boolean;
  /** Use File System Access API (default: false) */
  useFsAccessApi?: boolean;
  /** Auto focus the dropzone (default: false) */
  autoFocus?: boolean;
  /** Custom file aggregator function (default: fromEvent from file-selector) */
  getFilesFromEvent?: (event: DropEvent) => Promise<Array<File | DataTransferItem>>;
  /** Custom file validator (default: null) */
  validator?: <T extends File>(file: T) => FileError | readonly FileError[] | null;
  /** Callback when files are dropped */
  onDrop?: <T extends File>(
    acceptedFiles: T[],
    fileRejections: FileRejection[],
    event: DropEvent
  ) => void;
  /** Callback when files are accepted */
  onDropAccepted?: <T extends File>(files: T[], event: DropEvent) => void;
  /** Callback when files are rejected */
  onDropRejected?: (fileRejections: FileRejection[], event: DropEvent) => void;
  /** Callback when drag enters */
  onDragEnter?: (event: React.DragEvent<HTMLElement>) => void;
  /** Callback when drag leaves */
  onDragLeave?: (event: React.DragEvent<HTMLElement>) => void;
  /** Callback when dragging over */
  onDragOver?: (event: React.DragEvent<HTMLElement>) => void;
  /** Callback when file dialog opens */
  onFileDialogOpen?: () => void;
  /** Callback when file dialog is cancelled */
  onFileDialogCancel?: () => void;
  /** Error handler */
  onError?: (error: Error) => void;
}

interface DropzoneState {
  /** Dropzone is focused */
  isFocused: boolean;
  /** Active drag is in progress */
  isDragActive: boolean;
  /** Dragged files are accepted */
  isDragAccept: boolean;
  /** Some dragged files are rejected */
  isDragReject: boolean;
  /** File dialog is open */
  isFileDialogActive: boolean;
  /** Array of accepted files */
  acceptedFiles: readonly FileWithPath[];
  /** Array of rejected files with errors */
  fileRejections: readonly FileRejection[];
  /** Reference to root element */
  rootRef: React.RefObject<HTMLElement>;
  /** Reference to input element */
  inputRef: React.RefObject<HTMLInputElement>;
  /** Get props for root container */
  getRootProps: <T extends DropzoneRootProps>(props?: T) => T;
  /** Get props for hidden file input */
  getInputProps: <T extends DropzoneInputProps>(props?: T) => T;
  /** Programmatically open file dialog */
  open: () => void;
}

Usage Examples:

import { useDropzone } from "react-dropzone";

// Basic file upload
const basic = useDropzone({
  onDrop: (files) => console.log("Dropped files:", files),
});

// With file type restrictions
const imageOnly = useDropzone({
  accept: {
    "image/*": [".jpeg", ".jpg", ".png", ".gif"],
  },
  onDrop: (files) => uploadImages(files),
});

// With size limits and multiple files
const documents = useDropzone({
  accept: {
    "application/pdf": [".pdf"],
    "application/msword": [".doc", ".docx"],
  },
  minSize: 1024, // 1KB minimum
  maxSize: 5242880, // 5MB maximum
  maxFiles: 3,
  onDropAccepted: (files) => handleAccepted(files),
  onDropRejected: (rejections) => handleRejected(rejections),
});

Dropzone Component

Convenience wrapper component using render prop pattern for the useDropzone hook.

/**
 * Convenience wrapper component for the useDropzone hook
 * @param props - Dropzone options plus children render function
 */
function Dropzone(
  props: DropzoneProps & React.RefAttributes<DropzoneRef>
): React.ReactElement;

interface DropzoneProps extends DropzoneOptions {
  /** Render function that receives dropzone state */
  children?(state: DropzoneState): React.ReactElement;
}

interface DropzoneRef {
  /** Programmatically open file dialog */
  open: () => void;
}

Usage Examples:

import Dropzone from "react-dropzone";

// Basic usage with render prop
<Dropzone onDrop={(files) => console.log(files)}>
  {({ getRootProps, getInputProps, isDragActive }) => (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      {isDragActive ? (
        <p>Drop files here...</p>
      ) : (
        <p>Drag files here or click to browse</p>
      )}
    </div>
  )}
</Dropzone>

// With imperative access via ref
const dropzoneRef = useRef<DropzoneRef>(null);

<Dropzone ref={dropzoneRef} onDrop={handleDrop}>
  {({ getRootProps, getInputProps }) => (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      <button onClick={() => dropzoneRef.current?.open()}>
        Browse Files
      </button>
    </div>
  )}
</Dropzone>

File Validation and Error Handling

Built-in validation system with detailed error reporting for rejected files.

/** Error codes for file validation failures */
enum ErrorCode {
  FileInvalidType = "file-invalid-type",
  FileTooLarge = "file-too-large",
  FileTooSmall = "file-too-small",
  TooManyFiles = "too-many-files",
}

interface FileError {
  /** Human-readable error message */
  message: string;
  /** Error code for programmatic handling */
  code: ErrorCode | string;
}

interface FileRejection {
  /** The rejected file */
  file: FileWithPath;
  /** Array of validation errors */
  errors: readonly FileError[];
}

interface FileWithPath extends File {
  /** File path (when available) */
  path?: string;
}

Usage Examples:

import { useDropzone, ErrorCode } from "react-dropzone";

const { getRootProps, getInputProps, fileRejections } = useDropzone({
  accept: { "image/*": [] },
  maxSize: 1048576, // 1MB
  onDropRejected: (rejections) => {
    rejections.forEach(({ file, errors }) => {
      console.log(`File ${file.name} rejected:`);
      errors.forEach((error) => {
        switch (error.code) {
          case ErrorCode.FileInvalidType:
            console.log("Invalid file type");
            break;
          case ErrorCode.FileTooLarge:
            console.log("File too large");
            break;
          default:
            console.log(error.message);
        }
      });
    });
  },
});

// Custom validator
const customValidation = useDropzone({
  validator: (file) => {
    if (file.name.includes("temp")) {
      return {
        code: "name-not-allowed",
        message: "Temporary files are not allowed",
      };
    }
    return null;
  },
});

Advanced Configuration

Advanced features for specialized use cases and enhanced user experience.

interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {
  /** Reference key for root element (default: "ref") */
  refKey?: string;
  [key: string]: any;
}

interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
  /** Reference key for input element (default: "ref") */
  refKey?: string;
}

interface Accept {
  /** MIME type keys with array of file extensions */
  [mimeType: string]: readonly string[];
}

type DropEvent =
  | React.DragEvent<HTMLElement>
  | React.ChangeEvent<HTMLInputElement>
  | DragEvent
  | Event
  | Array<FileSystemFileHandle>;

Usage Examples:

// File System Access API (modern browsers)
const modernFileAccess = useDropzone({
  useFsAccessApi: true,
  onDrop: (files) => console.log("Files selected:", files),
});

// Custom file processing
const customProcessor = useDropzone({
  getFilesFromEvent: async (event) => {
    // Custom file extraction logic
    const items = Array.from(event.dataTransfer?.items || []);
    return items
      .filter((item) => item.kind === "file")
      .map((item) => item.getAsFile())
      .filter(Boolean);
  },
});

// Preventing document drops globally
const secureDropzone = useDropzone({
  preventDropOnDocument: true,
  noDragEventsBubbling: true,
  onDrop: (files) => secureUpload(files),
});

// Accessibility and keyboard support
const accessibleDropzone = useDropzone({
  autoFocus: true,
  noKeyboard: false, // Allow SPACE/ENTER to open dialog
  onDrop: (files) => handleFiles(files),
});

Types

/** File with optional path information */
interface FileWithPath extends File {
  path?: string;
}

/** Configuration for accepted file types */
interface Accept {
  [mimeType: string]: readonly string[];
}

/** Union type for various drop events */
type DropEvent =
  | React.DragEvent<HTMLElement>
  | React.ChangeEvent<HTMLInputElement>
  | DragEvent
  | Event
  | Array<FileSystemFileHandle>;

/** Error codes for file validation */
enum ErrorCode {
  FileInvalidType = "file-invalid-type",
  FileTooLarge = "file-too-large",
  FileTooSmall = "file-too-small",
  TooManyFiles = "too-many-files",
}

/** File validation error */
interface FileError {
  message: string;
  code: ErrorCode | string;
}

/** Rejected file with associated errors */
interface FileRejection {
  file: FileWithPath;
  errors: readonly FileError[];
}

docs

index.md

tile.json