44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
|
import { useEffect, useState } from "react";
|
||
|
|
||
|
type ReadAsMethod = "readAsText" | "readAsDataURL" | "readAsArrayBuffer" | "readAsBinaryString";
|
||
|
|
||
|
type UseFileReaderProps = {
|
||
|
method: ReadAsMethod;
|
||
|
onLoad?: (result: unknown) => void;
|
||
|
};
|
||
|
|
||
|
export const useFileReader = (options: UseFileReaderProps) => {
|
||
|
const { method = "readAsText", onLoad } = options;
|
||
|
const [file, setFile] = useState<File | null>(null);
|
||
|
const [loading, setLoading] = useState<boolean>(false);
|
||
|
const [error, setError] = useState<DOMException | null>(null);
|
||
|
const [result, setResult] = useState<string | ArrayBuffer | null>(null);
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (!file && result) {
|
||
|
setResult(null);
|
||
|
}
|
||
|
}, [file, result]);
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (!file) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const reader = new FileReader();
|
||
|
reader.onloadstart = () => setLoading(true);
|
||
|
reader.onloadend = () => setLoading(false);
|
||
|
reader.onerror = () => setError(reader.error);
|
||
|
|
||
|
reader.onload = (e: ProgressEvent<FileReader>) => {
|
||
|
setResult(e.target?.result ?? null);
|
||
|
if (onLoad) {
|
||
|
onLoad(e.target?.result ?? null);
|
||
|
}
|
||
|
};
|
||
|
reader[method](file);
|
||
|
}, [file, method, onLoad]);
|
||
|
|
||
|
return [{ result, error, file, loading }, setFile] as const;
|
||
|
};
|