UNPKG

react-files-hooks

Version:

React hooks for downloading and uploading files in the browsers

131 lines (113 loc) 3.89 kB
import { useRef, useEffect, MutableRefObject } from 'react'; import { defaultDownloadConfig, errorMessages } from '../constants'; import { DownloadService } from '../download-service/download.service'; const { defaultType, defaultEvent, defaultName } = defaultDownloadConfig; /** @module Downloader */ /** * Object for inserting to html element * @interface * @global * @typedef {{ref: MutableRefObject<HTMLElement>}} DownloadRefContainer * @property {MutableRefObject<HTMLElement>} ref - Reference to html element. */ /** * Manual downloading config * @interface * @global * @typedef ManualDownloadConfig * @property data {string|Object} - Downloaded data. Required. * @property name {string} - Name of downloaded data. Optional. Default - "file" * @property type {string} - Type of downloaded data. Optional. Default - "text/plain" */ /** * Function to download file * @interface * @global * @typedef {function} DownloadFn * @param config {ManualDownloadConfig} Manual downloading config * @return {Promise<void>} Promises resolves after downloading file. */ /** * Object to manage downloading files * @interface * @global * @typedef DownloadManager * @property {DownloadRefContainer} downloader - Object for inserting to html element. * @property {DownloadFn} download - Function to download file. */ /** * Downloading config * @interface * @global * @typedef DownloadConfig * @property data {string|Object} - Downloaded data. Required. * @property name {string} - Name of downloaded data. Optional. Default - "file" * @property type {string} - Type of downloaded data. Optional. Default - "text/plain" * @property event {string} - Event that triggers downloading. Optional. Default - "click" * @property onDownloaded {function} - Function is called after successful downloading. Optional * @property onError {function} - Function is called after failed downloading. Optional */ /** * Hook for downloading data * @param config {DownloadConfig} - Downloading config. * @return {DownloadManager} - Object to manage downloading files. * @function */ export function useDownloader( { data, onDownloaded, onError, name = defaultName, type = defaultType, event = defaultEvent } = {} ) { /** * Instance of DownloadService * @type {DownloadService} */ const downloadService = new DownloadService(); /** * Reference to trigger (HTMLElement) */ const triggerRef = useRef(null); /** * Dispatch event about error * @param error {Error} - Instance of Error object */ const handleError = error => { if (onError && typeof onError === 'function') { return onError(error); } }; /** \ * Download file * @param config {ManualDownloadConfig} - Manual downloading config. * @return {Promise<void>} Promise resolves after downloading file */ const download = async ({ data, name = defaultName, type = defaultType }) => { if (!data) throw new Error(errorMessages.noData); await downloadService.download(data, name, type); }; /** * Handle trigger event */ const handleTrigger = async () => { try { await download({ data, name, type }); if (onDownloaded && typeof onDownloaded === 'function') { onDownloaded(); } } catch (e) { handleError(e); } }; /** * Hook for adding/removing trigger listener */ useEffect(() => { const element = triggerRef.current; if (element) element.addEventListener(event, handleTrigger); return () => { if (element) element.removeEventListener(event, handleTrigger); }; }, [triggerRef, event]); // eslint-disable-line return { downloader: { ref: triggerRef }, download }; }