A React hook for integrating with the File System Access API. Enables web applications to seamlessly work with files on a user's local system.
npm install use-fsA React hook for integrating with the File System Access API. Visit use-fs.com to try it out in your browser.
The File System Access API enables web applications to seamlessly work with files on a user's local system. After a user grants permission, web apps can read, write, and manage files directly - eliminating the need for repeated file selection dialogs. This capability is ideal for creating powerful browser-based tools.
Unlike traditional file selection dialogs, the user will be prompted to select a directory, the hook will watch the files in that directory for changes - rerendering when changes are detected.
> ⚠️ Note: The File System API is not supported in all browsers. Works on Desktop in Chrome, Edge and Opera.
``console
npm install use-fs
yarn add use-fs
pnpm add use-fs
`
> 👋 Hello there! Follow me @linesofcode or visit linesofcode.dev for more cool projects like this one.
`tsx
import { useFs } from "use-fs";
function App() {
const {
onDirectorySelection,
files,
isBrowserSupported,
onClear,
isProcessing,
writeFile,
deleteFile,
startPolling,
stopPolling,
isPolling
} = useFs({
// Optional array of filter functions to exclude files/directories. By default commonFilters is used to ignore .git, node_modules, etc.
filters: [
// Built-in filters available:
// - distFilter (excludes dist/, build/, node_modules/, etc.)
// - gitFilter (respects .gitignore)
// - miscFilter (excludes .DS_Store, etc.)
// Or use commonFilters which includes all of the above
],
// Called when new files are added to the watched directory
onFilesAdded: (newFiles, previousFiles) => {
console.log('Files added:', newFiles);
// newFiles: Map
// previousFiles: Map
},
// Called when existing files are modified
onFilesChanged: (changedFiles, previousFiles) => {
console.log('Files changed:', changedFiles);
// changedFiles: Map
// previousFiles: Map
},
// Called when files are deleted from the watched directory
onFilesDeleted: (deletedFiles, previousFiles) => {
console.log('Files deleted:', deletedFiles);
// deletedFiles: Map
// previousFiles: Map
},
});
if (!isBrowserSupported) {
return
const handleSaveFile = async (path: string, content: string) => {
try {
await writeFile(path, content, { truncate: true });
console.log('File saved successfully');
} catch (error) {
console.error('Error saving file:', error);
}
};
const handleDeleteFile = async (path: string) => {
try {
await deleteFile(path);
console.log('File deleted successfully');
} catch (error) {
console.error('Error deleting file:', error);
}
};
return (
onClick={onClear}
disabled={isProcessing}
>
Clear
onClick={startPolling}
disabled={isProcessing || isPolling}
>
Start Polling
onClick={stopPolling}
disabled={isProcessing || !isPolling}
>
Stop Polling
{files.size > 0 && (
{content}The hook provides several key features:
1. File System Access: Prompts users to select a directory and maintains access to it.
2. File Writing: Allows writing content to files with options for truncation and creation.
3. File Deletion: Enables safe removal of files from the selected directory.
4. File Watching: Continuously monitors selected directory for changes with automatic polling.
5. Polling Control: Manual control over when to start/stop monitoring for file changes.
6. Content Management: Provides access to file contents and updates in real-time.
7. Filtering: Built-in and custom filters to exclude unwanted files/directories.
8. Performance Optimizations:
- Batched file processing
- Content caching
- Debounced updates
- Efficient change detection
$3
-
filters?: FilterFn[] - Array of filter functions to exclude files/directories
- onFilesAdded?: (newFiles: Map - Callback when files are added
- onFilesChanged?: (changedFiles: Map - Callback when files change
- onFilesDeleted?: (deletedFiles: Map - Callback when files are deleted
- pollInterval?: number - How often to check for changes (default: 100ms)
- batchSize?: number - How many files to process in parallel (default: 50)
- debounceInterval?: number - Debounce interval for updates (default: 50ms)
- fileCacheTtl?: number - How long to cache file contents (default: 5000ms)$3
-
onDirectorySelection: () => Promise - Function to open directory picker
- onClear: () => void - Function to stop watching and clear state
- files: Map - Current map of file paths to contents
- isProcessing: boolean - Whether files are being processed
- isBrowserSupported: boolean - Whether File System API is supported
- writeFile: (path: string, data: string | ArrayBuffer | Blob, options?: FileWriteOptions) => Promise - Function to write to files
- deleteFile: (path: string) => Promise - Function to delete files
- startPolling: () => void - Function to manually start polling for file changes
- stopPolling: () => void - Function to manually stop polling for file changes
- isPolling: boolean - Whether the hook is actively polling for changes
📚 Contributing
1. Navigate to the
docs directory
2. Run pnpm install to install the dependencies
3. Run pnpm dev to start the development server
3. Navigate to http://localhost:3000 to view the demo.
5. Modify the Demo.tsx file to make your changes.If you're making changes to the
use-fs package, you can run pnpm build to build the package and then run pnpm link use-fs to link the package to the docs` directory for local development and testing.