Skip to main content
useFileDialog provides an imperative API for opening the native file picker. The hook creates and manages a hidden <input type="file">, stores selected files in state, and exposes helpers to open or reset the current selection.

Usage

import { useFileDialog } from '@kuzenbo/hooks';

function Demo() {
  const { open, files } = useFileDialog();

  return (
    <div>
      <button onClick={open}>Select Files</button>
      {files && (
        <ul>
          {Array.from(files).map((file, index) => (
            <li key={index}>{file.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

API Reference

Parameters

options
UseFileDialogOptions
Optional file dialog configuration.
options.multiple
boolean
default:"true"
Determines whether multiple files are allowed.
options.accept
string
default:"*"
accept attribute of the file input (e.g., image/*, .pdf,.doc).
options.capture
string
capture attribute of the file input for mobile camera access.
options.directory
boolean
default:"false"
Determines whether the user can pick a directory instead of files.
options.resetOnOpen
boolean
default:"false"
Determines whether the file input state should be reset when the dialog is opened.
options.initialFiles
FileList | File[]
Initial selected files.
options.onChange
(files: FileList | null) => void
Called when files are selected.
options.onCancel
() => void
Called when file dialog is canceled.

Returns

files
FileList | null
Currently selected files.
open
() => void
Function to open the file picker dialog.
reset
() => void
Function to reset the current file selection.

Single File Selection

import { useFileDialog } from '@kuzenbo/hooks';

function Avatar() {
  const { open, files, reset } = useFileDialog({
    multiple: false,
    accept: 'image/*',
  });

  return (
    <div>
      <button onClick={open}>Choose Avatar</button>
      {files && files[0] && (
        <div>
          <p>{files[0].name}</p>
          <button onClick={reset}>Clear</button>
        </div>
      )}
    </div>
  );
}

With onChange Callback

import { useFileDialog } from '@kuzenbo/hooks';
import { useCallback } from 'react';

function Upload() {
  const handleChange = useCallback((selectedFiles: FileList | null) => {
    if (selectedFiles) {
      console.log('Selected files:', Array.from(selectedFiles));
    }
  }, []);

  const { open } = useFileDialog({ onChange: handleChange });

  return <button onClick={open}>Upload Files</button>;
}

File Type Restrictions

import { useFileDialog } from '@kuzenbo/hooks';

function DocumentPicker() {
  const { open, files } = useFileDialog({
    accept: '.pdf,.doc,.docx',
    multiple: false,
  });

  return (
    <div>
      <button onClick={open}>Select Document</button>
      {files?.[0] && <p>Selected: {files[0].name}</p>}
    </div>
  );
}

Directory Selection

import { useFileDialog } from '@kuzenbo/hooks';

function FolderPicker() {
  const { open, files } = useFileDialog({
    directory: true,
  });

  return (
    <div>
      <button onClick={open}>Select Folder</button>
      {files && <p>{files.length} files in folder</p>}
    </div>
  );
}

Image Upload with Preview

import { useFileDialog } from '@kuzenbo/hooks';
import { useState } from 'react';

function ImageUpload() {
  const [preview, setPreview] = useState<string | null>(null);

  const { open, files, reset } = useFileDialog({
    accept: 'image/*',
    multiple: false,
    onChange: (selectedFiles) => {
      if (selectedFiles?.[0]) {
        const reader = new FileReader();
        reader.onload = (e) => setPreview(e.target?.result as string);
        reader.readAsDataURL(selectedFiles[0]);
      }
    },
  });

  const handleReset = () => {
    reset();
    setPreview(null);
  };

  return (
    <div>
      <button onClick={open}>Select Image</button>
      {preview && (
        <div>
          <img src={preview} alt="Preview" style={{ maxWidth: 200 }} />
          <button onClick={handleReset}>Remove</button>
        </div>
      )}
    </div>
  );
}

Mobile Camera Capture

import { useFileDialog } from '@kuzenbo/hooks';

function CameraCapture() {
  const { open, files } = useFileDialog({
    accept: 'image/*',
    capture: 'environment', // Use rear camera
    multiple: false,
  });

  return <button onClick={open}>Take Photo</button>;
}

Build docs developers (and LLMs) love