useXmlHttpUpload()

A hook to upload a file with progress tracking, request abortion etc.

This hook may be used to upload a file to an S3 bucket using a pre-signed upload URL.

This hook makes use of useResettableState().

function useXmlHttpUpload(file: File) {
  const [progress, setProgress, resetProgress] = useResettableState(0);
  const [isUploading, setIsUploading, resetIsUploading] =
    useResettableState(false);
  const [isError, setIsError, resetIsError] = useResettableState(false);
  const [isAborted, setIsAborted, resetIsAborted] = useResettableState(false);
  const [isComplete, setIsComplete, resetIsCompleted] =
    useResettableState(false);
  const internalRequest = useRef<XMLHttpRequest | null>();

  function resetState() {
    resetProgress();
    resetIsUploading();
    resetIsError();
    resetIsAborted();
    resetIsCompleted();

    internalRequest.current = null;
  }

  function upload(uploadUrl: string) {
    resetState();
    setIsUploading(true);

    const request = new XMLHttpRequest();
    internalRequest.current = request;

    request.open("PUT", uploadUrl);
    request.setRequestHeader("Content-Type", file.type);

    request.upload.addEventListener("progress", (e) => {
      setProgress((e.loaded / e.total) * 100);
    });

    request.addEventListener("load", () => {
      resetState();
      setIsComplete(true);
    });
    request.addEventListener("error", () => {
      resetState();
      setIsError(true);
    });

    request.send(file);
  }

  return {
    upload,
    isError,
    isUploading,
    isComplete,
    isAborted,
    progress,
    abort,
  };
}