SkillAgentSearch skills...

UseFilePicker

Simple react hook to open browser file selector.

Install / Use

/learn @Jaaneek/UseFilePicker
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<center>Welcome to use-file-picker 👋</center>

Simple react hook to open browser file selector.

alt Version alt License: MIT alt Twitter: twitter.com/jaaneek/

🏠 Homepage

Documentation

Install

npm i use-file-picker or yarn add use-file-picker

Usage

Simple txt file content reading

import { useFilePicker } from 'use-file-picker';
import React from 'react';

export default function App() {
  const { openFilePicker, filesContent, loading } = useFilePicker({
    accept: '.txt',
  });

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <button onClick={() => openFilePicker()}>Select files</button>
      <br />
      {filesContent.map((file, index) => (
        <div key={index}>
          <h2>{file.name}</h2>
          <div key={index}>{file.content}</div>
          <br />
        </div>
      ))}
    </div>
  );
}

Reading and rendering Images

import { useFilePicker } from 'use-file-picker';
import {
  FileAmountLimitValidator,
  FileTypeValidator,
  FileSizeValidator,
  ImageDimensionsValidator,
} from 'use-file-picker/validators';

export default function App() {
  const { openFilePicker, filesContent, loading, errors } = useFilePicker({
    readAs: 'DataURL',
    accept: 'image/*',
    multiple: true,
    validators: [
      new FileAmountLimitValidator({ max: 1 }),
      new FileTypeValidator(['jpg', 'png']),
      new FileSizeValidator({ maxFileSize: 50 * 1024 * 1024 /* 50 MB */ }),
      new ImageDimensionsValidator({
        maxHeight: 900, // in pixels
        maxWidth: 1600,
        minHeight: 600,
        minWidth: 768,
      }),
    ],
  });

  if (loading) {
    return <div>Loading...</div>;
  }

  if (errors.length) {
    return <div>Error...</div>;
  }

  return (
    <div>
      <button onClick={() => openFilePicker()}>Select files </button>
      <br />
      {filesContent.map((file, index) => (
        <div key={index}>
          <h2>{file.name}</h2>
          <img alt={file.name} src={file.content}></img>
          <br />
        </div>
      ))}
    </div>
  );
}

On change callbacks

import { useFilePicker } from 'use-file-picker';

export default function App() {
  const { openFilePicker, filesContent, loading, errors } = useFilePicker({
    readAs: 'DataURL',
    accept: 'image/*',
    multiple: true,
    onFilesSelected: ({ plainFiles, filesContent, errors }) => {
      // this callback is always called, even if there are errors
      console.log('onFilesSelected', plainFiles, filesContent, errors);
    },
    onFilesRejected: ({ errors }) => {
      // this callback is called when there were validation errors
      console.log('onFilesRejected', errors);
    },
    onFilesSuccessfullySelected: ({ plainFiles, filesContent }) => {
      // this callback is called when there were no validation errors
      console.log('onFilesSuccessfullySelected', plainFiles, filesContent);
    },
  });

  if (loading) {
    return <div>Loading...</div>;
  }

  if (errors.length) {
    return <div>Error...</div>;
  }

  return (
    <div>
      <button onClick={() => openFilePicker()}>Select files </button>
      <br />
      {filesContent.map((file, index) => (
        <div key={index}>
          <h2>{file.name}</h2>
          <img alt={file.name} src={file.content}></img>
          <br />
        </div>
      ))}
    </div>
  );
}

Advanced usage

import { useFilePicker } from 'use-file-picker';
import React from 'react';

export default function App() {
  const { openFilePicker, filesContent, loading, errors, plainFiles, clear } = useFilePicker({
    multiple: true,
    readAs: 'DataURL', // availible formats: "Text" | "BinaryString" | "ArrayBuffer" | "DataURL"
    // accept: '.ics,.pdf',
    accept: ['.json', '.pdf'],
    validators: [new FileAmountLimitValidator({ min: 2, max: 3 })],
    // readFilesContent: false, // ignores file content
  });

  if (errors.length) {
    return (
      <div>
        <button onClick={() => openFilePicker()}>Something went wrong, retry! </button>
        {errors.map(err => (
          <div>
            {err.name}: {err.reason}
            /* e.g. "name":"FileAmountLimitError", "reason":"MAX_AMOUNT_OF_FILES_EXCEEDED" */
          </div>
        ))}
      </div>
    );
  }

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <button onClick={() => openFilePicker()}>Select file </button>
      <button onClick={() => clear()}>Clear</button>
      <br />
      Number of selected files:
      {plainFiles.length}
      <br />
      {/* If readAs is set to DataURL, You can display an image */}
      {!!filesContent.length && <img src={filesContent[0].content} />}
      <br />
      {plainFiles.map(file => (
        <div key={file.name}>{file.name}</div>
      ))}
    </div>
  );
}

Callbacks

You can hook your logic into callbacks that will be fired at specific events during the lifetime of the hook. useFilePicker accepts these callbacks:

  • onFilesSelected
  • onFilesRejected
  • onFilesSuccessfullySelected
  • onClear

These are described in more detail in the Props section.

import { useFilePicker } from 'use-file-picker';

export default function App() {
  const { openFilePicker, filesContent, loading, errors, plainFiles, clear } = useFilePicker({
    multiple: true,
    readAs: 'DataURL',
    accept: ['.json', '.pdf'],
    onFilesSelected: ({ plainFiles, filesContent, errors }) => {
      // this callback is always called, even if there are errors
      console.log('onFilesSelected', plainFiles, filesContent, errors);
    },
    onFilesRejected: ({ errors }) => {
      // this callback is called when there were validation errors
      console.log('onFilesRejected', errors);
    },
    onFilesSuccessfullySelected: ({ plainFiles, filesContent }) => {
      // this callback is called when there were no validation errors
      console.log('onFilesSuccessfullySelected', plainFiles, filesContent);
    },
    onClear: () => {
      // this callback is called when the selection is cleared
      console.log('onClear');
    },
  });
}

useImperativePicker hook also accepts the callbacks listed above. Additionally, it accepts the onFileRemoved callback, which is called when a file is removed from the list of selected files.

import { useImperativeFilePicker } from 'use-file-picker';

export default function App() {
  const { openFilePicker, filesContent, loading, errors, plainFiles, clear } = useImperativeFilePicker({
    onFileRemoved: (removedFile, removedIndex) => {
      // this callback is called when a file is removed from the list of selected files
      console.log('onFileRemoved', removedFile, removedIndex);
    },
  });
}

Keeping the previously selected files and removing them from selection on demand

If you want to keep the previously selected files and remove them from the selection, you can use a separate hook called useImperativeFilePicker that is also exported in this package. For files removal, you can use removeFileByIndex or removeFileByReference functions.

import React from 'react';
import { useImperativeFilePicker } from 'use-file-picker';

const Imperative = () => {
  const { openFilePicker, filesContent, loading, errors, plainFiles, clear, removeFileByIndex, removeFileByReference } =
    useImperativeFilePicker({
      multiple: true,
      readAs: 'Text',
      readFilesContent: true,
    });

  if (errors.length) {
    return (
      <div>
        <button onClick={() => openFilePicker()}>Something went wrong, retry! </button>
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {console.log(errors)}
          {errors.map(err => (
            <div>
              {err.name}: {err.reason}
              /* e.g. "name":"FileAmountLimitError", "reason":"MAX_AMOUNT_OF_FILES_EXCEEDED" */
            </div>
          ))}
        </div>
      </div>
    );
  }

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <button onClick={async () => openFilePicker()}>Select file</button>
      <button onClick={() => clear()}>Clear</button>
      <br />
      Amount of selected files:
      {plainFiles.length}
      <br />
      Amount of filesContent:
      {filesContent.length}
      <br />
      {plainFiles.map((file, i) => (
        <div>
          <div style={{ display: 'flex', alignItems: 'center' }} key={file.name}>
            <div>{file.name}</div>
            <button style={{ marginLeft: 24 }} onClick={() => removeFileByReference(file)}>
              Remove by reference
            </button>
            <button style={{ marginLeft: 24 }} onClick={() => removeFileByIndex(i)}>
              Remove by index
            </button>
          </div>
          <div>{filesContent[i]?.content}</div>
        </div>
      ))}
    </div>
  );
};
``
View on GitHub
GitHub Stars304
CategoryDevelopment
Updated2mo ago
Forks34

Languages

TypeScript

Security Score

95/100

Audited on Jan 15, 2026

No findings